实际上,我正在使用OpenCV和Python开发一个机器视觉项目。
目标:项目的目标是以高精度测量组件的尺寸。
主要硬件:
巴斯勒5MP照相机(aca-2500-14gm)
一个红色背光灯(100毫米x 100毫米)(我的组件大小约为60毫米)
实验
因为我正在考虑非常严格的公差限制,所以我首先做了一个精确的研究。我把组件放在背光源上,在不移动部件的情况下拍摄了100张图像(想象一下100帧的视频)。我测量了所有100幅图像的外径。我的毫米/像素比是0.042。我测量了测量的标准偏差,以确定精度,结果是0.03mm,这是不好的。组件和设置都没有接触,因此我希望精度为0.005mm。但我的损失是一个数量级的。我使用OpenCV的Hough圆来计算组件的OD。
代码:
import sys
import pickle
import cv2
import matplotlib.pyplot as plt
import glob
import os
import numpy as np
import pandas as pd
def find_circles(image,dp=1.7,minDist=100,param1=50,param2=50,minRadius=0,maxRadius=0):
""" finds the center of circular objects in image using hough circle transform
Keyword arguments
image -- uint8: numpy ndarray of a single image (no default).
dp -- Inverse ratio of the accumulator resolution to the image resolution (default 1.7).
minDist -- Minimum distance in pixel distance between the centers of the detected circles (default 100).
param1 -- First method-specific parameter (default = 50).
param2 -- Second method-specific parameter (default = 50).
minRadius -- Minimum circle radius in pixel distance (default = 0).
maxRadius -- Maximum circle radius in pixel distance (default = 0).
Output
center -- tuple: (x,y).
radius -- int : radius.
ERROR if circle is not detected. returns(-1) in this case
"""
circles=cv2.HoughCircles(image,
cv2.HOUGH_GRADIENT,
dp = dp,
minDist = minDist,
param1=param1,
param2=param2,
minRadius=minRadius,
maxRadius=maxRadius)
if circles is not None:
circles = circles.reshape(circles.shape[1],circles.shape[2])
return(circles)
else:
raise ValueError("ERROR!!!!!! circle not detected try tweaking the parameters or the min and max radius")
def find_od(image_path_list):
image_path_list.sort()
print(len(image_path_list))
result_df = pd.DataFrame(columns=["component_name","measured_dia_pixels","center_in_pixels"])
for i,name in enumerate(image_path_list):
img = cv2.imread(name,0) # read the image in grayscale
ret,thresh_img = cv2.threshold(img, 50, 255, cv2.THRESH_BINARY_INV)
thresh_img = cv2.bilateralFilter(thresh_img,5,91,91) #smoothing
edges = cv2.Canny(thresh_img,100,200)
circles = find_circles(edges,dp=1.7,minDist=100,param1=50,param2=30,minRadius=685,maxRadius=700)
circles = np.squeeze(circles)
result_df.loc[i] = os.path.basename(name),circles[2]*2,(circles[0],circles[1])
result_df.sort_values("component_name",inplace=True)
result_df.reset_index(drop=True,inplace=True)
return(result_df)
df = find_od(glob.glob("./images/*"))
mean_d = df.measured_dia_pixels.mean()
std_deviation = np.sqrt(np.mean(np.square([abs(x-mean_d) for x in df.measured_dia_pixels])))
mm_per_pixel = 0.042
print(std_deviation * mm_per_pixel)
输出:0.024
组件的图像:
由于图像是在不干扰设置的情况下拍摄的,我预计测量的重复性大约为0.005mm(5微米)(对于100个图像),但事实并非如此。这是hough圆的问题吗?或者我在这里遗漏了什么
Hough设计用于检测,而不是用于量化。如果你想要精确的测量,你必须使用一个为此设计的库。OpenCV不是用来量化的,因此它的性能很差。
很久以前,我写过一篇关于使用Radon变换(Hough变换是Radon变换离散化的一种方法,在某些情况下速度很快,但不精确)更精确估计尺寸的论文:
但是因为你的设置是如此的好控制,你并不需要所有这些来得到一个精确的测量。下面是一个非常直接的Python脚本来量化这些漏洞:
这给了我输出:
注意上面的代码中有很多假设。还有一个问题是相机没有正中在物体的正上方,你可以看到孔的右侧反射光。这肯定会增加这些测量的不精确性。但也要注意的是,我在测量时并没有使用物体是圆的这一知识(仅在将面积转换为直径时)。也许可以使用圆度标准来克服一些成像缺陷。
以上代码使用pyDip,一个非常粗糙的Python接口到C++库,DIPlib 3。Python语法是C++语法的直接翻译,有些东西对于Python人来说仍然很难(实际上,在C++中,它更容易使用!)但它是专门针对量化的,因此我建议您在应用程序中试用它。
相关问题 更多 >
编程相关推荐