0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

カメラの一画素あたりのサイズを推定

Posted at

目的

カメラのセンサーサイズを紙と定規とEXIFで計算してみようを見ていて、
スマホならともかく、カメラだと長さ測るの無理じゃないと思って考えてみた。

やったこと

  1. 印刷したArUcoマーカーを10cm前後ずらして撮影
  2. 下記値を使って1Pixelあたりのサイズを算出
    1. 印刷したマーカーのサイズ[cm]
    2. それぞれのマーカーのPixelサイズ[px]
    3. 使用したレンズの焦点距離

結果

カタログで計算した値より小さくなってしまいました。
マーカーの位置が適当だったので、その影響かもです。
(マーカーが正面向いていないとか、レンズ中心じゃないと式が成り立たないとか)
あと、近いので実効焦点距離も影響しているかもです。

  • カタログから算出: 0.003756946[mm](サイズ: 17.3mm×13.0mm, 画素数: 4608×3456より)
  • 測定値から算出: 0.00363212270430662[mm]

詳細

マーカーの準備

適当にマーカを生成し印刷。サイズを測る。ここでは対角線の長さを測った(特に意図はない)。
角は測りにくかったので、辺の長さ(5.075cm)を測って計算。

import cv2
from cv2 import aruco
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)
marker = aruco.drawMarker(dictionary, 4, 112)
dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
img_mark = aruco.drawMarker(dict_aruco, 4, 180)
cv2.imwrite("aruco_maker.png", img_mark)

aruco_maker.png

マーカーを撮影

適当にマーカーを配置し複数枚撮影。その後10cm移動させて再度撮影。

サンプル

Pixelサイズを算出

撮影した画像を適当に配置。対角線のピクセル数を算出。何となく対角線2つを算出して平均。

import cv2
from cv2 import aruco

import matplotlib.pyplot as plt
from glob import glob
import os
import os.path
import numpy as np

dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
parameters = aruco.DetectorParameters_create()


for fn in glob("image_sensor/*.jpg"):
    # print(fn)
    img = cv2.imread(fn)
    # plt.imshow(img[...,::-1])
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dict_aruco, parameters=parameters)
    if ids is None:
        continue        
    
    cornerUL = corners[0][0][0]
    cornerUR = corners[0][0][1]
    cornerBR = corners[0][0][2]
    cornerBL = corners[0][0][3]

    center = [ (cornerUL[0]+cornerBR[0])/2 , (cornerUL[1]+cornerBR[1])/2 ]
    l1 = np.sqrt(np.sum((cornerUL - cornerBR) ** 2))
    l2 = np.sqrt(np.sum((cornerUR - cornerBL) ** 2))
    print(fn, center, (l1 + l2) / 2)
    
    img_markers = aruco.drawDetectedMarkers(img.copy(), corners, ids)
    # plt.imshow(img_markers[...,::-1])
    
    dn, bn = os.path.split(fn)
    bn, ext = os.path.splitext(bn)
    ofn = os.path.join(dn, "marker", f"{bn}_marker{ext}")
    os.makedirs(os.path.dirname(ofn), exist_ok=True)
    cv2.imwrite(ofn, img_markers)

複数撮った対角線の長さを平均。
近い距離の写真複数撮ったつもりだけど、結局2枚しかなかった・・・

  • 近いときp1: 1797.411194
  • 遠いときp2: 1089.5224
image_sensor\P5260067.JPG [2260.5, 2003.0] 1797.4017333984375
image_sensor\P5260068.JPG [2260.5, 2002.0] 1797.420654296875
image_sensor\P5260071.JPG [2271.5, 1961.5] 1090.2025146484375
image_sensor\P5260072.JPG [2273.0, 1960.0] 1089.5416259765625
image_sensor\P5260076.JPG [2272.0, 1960.5] 1089.177001953125
image_sensor\P5260077.JPG [2272.5, 1960.5] 1089.5181884765625
image_sensor\P5260078.JPG [2272.0, 1960.5] 1089.5185546875
image_sensor\P5260079.JPG [2272.5, 1960.5] 1089.176513671875

撮像時の関係

L
撮像した物体。今回はマーカーのサイズ
d
マーカーを移動させた距離。今回はカメラを10cm移動させたけど
f
焦点距離。今回は14mm
$a_1$, $a_2$
レンズから物体までの距離
$b_1$, $b_2$
レンズから像(=イメージセンサー)までの距離。
この絵ではレンズ位置は固定だけど、実際はレンズが動いてイメージセンサ上に像ができているはず
$l_1$, $l_2$
像の大きさ。$p_1, p_2$と比例するはず

image.png

図から下記関係を導出

変数は6個なので、1つ式余分だけど。。。

image.png

sympyで解く

import sympy as sy
sy.init_printing(use_unicode=False, wrap_line=True)

l1, l2, a1, a2, b1, b2, p1, p2, L, f, d = sy.symbols('l_1 l_2 a_1 a_2 b_1 b_2 p_1 p_2 L f d')


eq1 = sy.Eq(l1/l2, (b1-f)/(b2-f))
eq2 = sy.Eq(1/f, 1/a1 + 1/b1)
eq3 = sy.Eq(1/f, 1/a2 + 1/b2)
eq4 = sy.Eq(l2/L, b2/a2)
eq5 = sy.Eq(l1/L, b1/a1)
eq6 = sy.Eq(p1/p2, l1/l2)
eq7 = sy.Eq(a2, a1 + d)



dec = {f: 1.4, p1: 1797.411194, p2: 1089.5224, d: 10, L: sy.sqrt(2 * 5.075 ** 2)}
eqs = [eq1, eq2, eq3, eq4, eq5, eq6, eq7]
eqs = [e.subs(dec) for e in eqs]

sol = sy.solve(eqs)
for n,v in sol[0].items():
    display(sy.Eq(n, v))
print(f"1Pixelあたりのサイズ: {(l1/p1).subs(dec).subs(sol[0])}mm")

𝑎1=16.7911519610804 
𝑎2=26.7911519610804 
𝑏1=1.52734589359888 
𝑏2=1.4771922440937 
𝑙1=0.652841800670228 
𝑙2=0.395727904589064 
1Pixelあたりのサイズ: 0.000363212270430662mm
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?