问题描述
我一直在尝试使用 OpenCV python 中的参考对象(3x5 棋盘格)测量窗格,但我的测量值与实际值相差约 5-10%。有没有办法提高测量的精度?
我目前的方法:
- 使用不同角度的参考物体图像校准相机
- 使用
cv2.undistort()
查找未失真的图像 - 使用
findChessboardCorners()
查找参考对象的角 - 创建一组顶视点
- 使用
findHomography()
和warpPerspective()
将原始图像转换为俯视图 - 选择最有可能是窗玻璃边缘的四个点
- 根据 4 个角找到边缘像素
- 使用参考对象的角来求出每个正方形的大致长度
- 使用边缘像素计算窗玻璃的相对长度
- 使用实际长度和参考方块的长度求出比例,并使用该比例求出窗玻璃的实际长度
我在此附上使用的参考对象和图像。任何建议将不胜感激。提前致谢!
window_pane
窗玻璃的原始尺寸为 6x10 英寸。
import numpy as np
import cv2
import imutils
import math
import os
import base64
import json
from sys import argv
import sys
from google.colab.patches import cv2_imshow
def get_refrence_corners(image):
cornersList = []
# resized = imutils.resize(image,width=600)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,corners = cv2.findChessboardCorners(gray,(5,3),None)
print(ret)
# If found
if ret == True:
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,30,0.001)
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
for x in range(len(corners2)):
cornersList.append(corners2[x][0])
return cornersList
def get_corners(img_resized,sensitivity):
cornersList = []
imgGrey = cv2.cvtColor(img_resized,cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(imgGrey,sensitivity,0.01,60)
corners = np.float32(corners)
for corner in corners:
x,y = corner.ravel()
if x.item() > 325 or x.item() < 55 or y.item() > 1515 or y.item() < 1335:
cornersList.append((x.item(),y.item()))
return cornersList
def get_dist_two_points(point1,point2):
distX = abs(point1[0] - point2[0])
distY = abs(point1[1] - point2[1])
dist = math.sqrt(distX**2 + distY**2)
return dist
def get_edges_pixels(chosen,edge_pixels) :
biggest_sum = chosen[0][0] + chosen[0][1]
smallest_sum = chosen[0][0] + chosen[0][1]
smallest_corner = 0
biggest_corner = 0
for edge in range(len(chosen)):
if (chosen[edge][0] + chosen[edge][1]) > biggest_sum:
biggest_sum = (chosen[edge][0] + chosen[edge][1])
biggest_corner = edge
elif (chosen[edge][0] + chosen[edge][1]) < smallest_sum:
smallest_sum = (chosen[edge][0] + chosen[edge][1])
smallest_corner = edge
for corner in range(len(chosen)):
if corner != smallest_corner and corner != biggest_corner:
dist = get_dist_two_points(chosen[corner],chosen[smallest_corner])
edge_pixels.append(dist)
dist = get_dist_two_points(chosen[corner],chosen[biggest_corner])
edge_pixels.append(dist)
return edge_pixels
def get_relative_length(edge_pixels,refLength):
ref = (refLength[1] + refLength[0]) / 2
average_x = (edge_pixels[0] + edge_pixels[3]) / 2
average_y = (edge_pixels[1] + edge_pixels[2]) / 2
x = (average_x / ref)
y = (average_y / ref)
length = [x * 17/32,y * 17/32]
return length
def get_refrence_length(image):
gray = cv2.cvtColor(image,None)
if ret == True:
avg_horz = 0
avg_virt = 0
edges_horz = 0
edges_virt = 0
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,criteria)
for x in range (14):
if ((x + 1) % 5) != 0 :
avg_virt += get_dist_two_points(corners2[x][0],corners2[x+1][0])
edges_virt += 1
# if the point is in the row skip the comparison as there is no points on the left
if (x + 5) <= 14 :
avg_horz += get_dist_two_points(corners2[x][0],corners2[x+5][0])
edges_horz += 1
return [avg_horz / edges_horz,avg_virt / edges_virt]
imgpoints = np.load('/content/imgpoints.pkl',allow_pickle=True)
objpoints = np.load('/content/objpoints.pkl',allow_pickle=True)
path = '/content/IMG_4854.JPG'
image = cv2.imread(path)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,mtx,dist,rvecs,tvecs = cv2.calibrateCamera(objpoints,imgpoints,gray.shape[::-1],None,None)
img = cv2.imread('/content/IMG_4854.JPG')
h,w = img.shape[:2]
newcameramtx,roi=cv2.getoptimalNewCameraMatrix(mtx,(w,h),1,h))
# undistort
dst = cv2.undistort(img,newcameramtx)
# crop the image
x,y,w,h = roi
dst = dst[y:y+h,x:x+w]
cv2.imwrite('calibresult.png',dst)
finalImage = cv2.imread('/content/calibresult.png')
grayFinal = cv2.cvtColor(finalImage,cv2.COLOR_BGR2GRAY)
reference_corners = get_refrence_corners(finalImage)
reference_corners = np.float32(reference_corners)
sorted_reference_points = np.array(sorted(reference_corners,key = lambda x: x[1]))
top_view_points = np.float32([(200,1380),(245,(290,(335,(380,(200,1425),1470),1470)])
sorted_top_view_points = top_view_points[top_view_points[:,0].argsort()]
print(sorted_top_view_points)
M,mask = cv2.findHomography(sorted_reference_points,top_view_points,cv2.RANSAC,5.0)
dst = cv2.warpPerspective(finalImage,M,(1080,1920),flags = cv2.INTER_CUBIC,borderMode=cv2.BORDER_CONSTANT,borderValue = [0,0])
dst_path = '/content/dst.jpeg'
cv2.imwrite(dst_path,dst)
corners = get_corners(dst,100)
corners = np.float32(corners)
chosen_corners = [(90,560),(700,570),(150,1510),(632,1510)]
chosen_corners = np.int0(chosen_corners)
edge_pixels = []
edge_pixels = get_edges_pixels(chosen_corners,edge_pixels)
reference_length = get_refrence_length(dst)
measurement = get_relative_length(edge_pixels,reference_length)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)