利用单应变换矩阵进行度量矫正
测试图像来自于网络
1 理论分析
根据射影几何相关理论,在2D射影空间内,要想得到两张图像的对应关系,最重要的是得到其单应变换矩阵H。矩阵H共有8个未知数,至少需要4个对应点对才能进行单应变换估计。假设胶片图像长宽比为4:3。
- 先利用Canny算子检测边缘点;
- 再进行Hough直线检测,得到边缘点检测胶片边缘对应的4条直线; 4条直线在图像平面中的交点则为胶片图像的4个顶点。这4个顶点和真实世界中的胶片顶点组成4个对应点对;
- 得到两个平面之间的单应变换矩阵,完成度量矫正。
2 实践结果
2.1 Canny 边缘检测
2.2 Hough直线检测
#利用Hough变换找到直线,分类,画出直线,并保存
def find_lines(img,lines,save_path):
im = img.copy()
h_lines=[]
v_lines=[]
#将所得直线分为水平直线和垂直直线
for i in range(lines.shape[0]):
if lines[i,0,1] > (3.14*0.25) and lines[i,0,1] < (3.14*0.75):
v_lines.append(lines[i,:,:])
else:
h_lines.append(lines[i,:,:])
# 在图中画出所得直线
for line in v_lines:
for rho,theta in line:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 2000*(-b))
y1 = int(y0 + 2000*(a))
x2 = int(x0 - 2000*(-b))
y2 = int(y0 - 2000*(a))
cv2.line(im,(x1,y1),(x2,y2),(0,255,0),2)
for line in h_lines:
for rho,theta in line:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 2000*(-b))
y1 = int(y0 + 2000*(a))
x2 = int(x0 - 2000*(-b))
y2 = int(y0 - 2000*(a))
cv2.line(im,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imwrite(save_path+'.jpg',im)
return im,h_lines,v_lines
2.3 求解交点(矩阵求解)
利用线性代数对于直线的参数矩阵求逆,快速计算得到两直线交点。
#计算两条直线交点
def cross_point(line1,line2):
rho1,theta1 = line1[0]
rho2,theta2 = line2[0]
A = np.array([
[np.cos(theta1),np.sin(theta1)],
[np.cos(theta2),np.sin(theta2)]
])
b = np.array([[rho1],[rho2]])
x0,y0 = np.linalg.solve(A,b)
x0,y0 = int(x0),int(y0)
return [x0,y0]
利用所有交点得到其几何中心,以几何中心为原点,选取4个交点作为待
矫正图像的4个顶点。细节参照代码。
2.4 得到单应变换矩阵,进行单应变换。
# 利用交点计算单应变换矩阵,并保存结果
def transform(img,points,save_path):
scr = np.float32(points)
dst = []
center = np.mean(points,axis=0)
for i in scr:
if i[0] > center[0] and i[1] > center[1]:
dst.append([800,600])
elif i[0] < center[0] and i[1] < center[1]:
dst.append([0,0])
elif i[0] > center[0] and i[1] < center[1]:
dst.append([800,0])
elif i[0] < center[0] and i[1] > center[1]:
dst.append([0,600])
dst = np.asarray(dst,dtype=np.float32)
m = cv2.getPerspectiveTransform(scr,dst)
result = cv2.warpPerspective(img,m,(800,600))
cv2.imwrite(save_path+'.jpg',result)