問題描述
我實際上正在使用 OpenCV 和 Python 進行機器視覺項目.
I am actually working on a Machine Vision project using OpenCV and Python.
目標:該項目的目標是高精度測量組件的尺寸.
Objective : The objective of the project is to measure the dimensions of a component with high accuracy.
主要硬件:
Basler 5MP 相機 (aca-2500-14gm)
Basler 5MP camera (aca-2500-14gm)
紅色背光燈(100 mm x 100 mm)(我的組件尺寸約為 60mm)
A red backlight (100 mm x 100 mm) (Size of my component is around 60mm)
實驗
由于我正在查看非常嚴格的公差限制,因此我首先進行了精確研究.我將組件保留在背光源上,并在不移動部件的情況下拍攝了 100 張圖像(想象一下,就像一個 100 幀的視頻).我測量了所有 100 張圖像的外徑(OD).我的毫米/像素比率是 0.042.我測量了測量的標準偏差以找出精度,結果發現它在 0.03 mm 左右,這很糟糕.組件和設置都沒有被觸及,因此我期望的精度為 0.005 毫米.但我差了一個數量級.我正在使用 OpenCV 的霍夫圓來計算組件的外徑.
Since I am Looking at very tight tolerance limits, I first did a precision study. I kept the component on the backlight source and took 100 images without moving the part (imagine like a video with 100 frames). I measured the Outer Diameter(OD) of all the 100 images. My mm/pixel ratio is 0.042. I measured the standard deviation of the measurement to find out the precision, which turned out to be around 0.03 mm which is bad. The component nor the setup is touched thus I was expecting a precision of 0.005 mm. But I am off by an order of magnitude. I am using OpenCV's Hough circle to calculate the OD of the component.
代碼:
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.005 毫米(5 微米)(對于 100 張圖像).但事實并非如此.是霍夫圓的問題嗎?或者我在這里錯過了什么
Since the Images are taken without disturbing the setup, I expect the measurement's repeatability to be around 0.005 mm (5 microns) (For 100 images).But this is not so. Is it a problem of hough circle? or what am I missing here
推薦答案
霍夫設計用于檢測,而不是量化.如果您想要精確測量,則必須使用為此設計的庫.OpenCV 不適合量化,因此在這方面的能力很差.
Hough is designed for detecting, not for quantifying. If you want precise measures, you'll have to use a library designed for that. OpenCV is not meant for quantification, and consequently has poor capabilities there.
很久以前,我寫了一篇關于使用 Radon 變換更精確地估計大小的論文(Hough 變換是對 Radon 變換進行離散化的一種方法,在某些情況下速度很快,但并不精確):
A long time ago I wrote a paper about more precise estimates of size using the Radon transform (the Hough transform is one way of discretizing the Radon transform, it's fast for some cases, but not precise):
- C.L.Luengo Hendriks, M. van Ginkel, P.W.Verbeek 和 LJ van Vliet,廣義 Radon 變換:采樣、精度和內存考慮,模式識別 38(12):2494–2505, 2005,doi:10.1016/j.patcog.2005.04.018.這是一個 PDF.
但由于您的設置控制得非常好,因此您實際上并不需要所有這些來獲得精確的測量值.這是一個非常簡單的 Python 腳本來量化這些漏洞:
But because your setup is so well controlled, you don't really need all that to get a precise measure. Here is a very straight-forward Python script to quantify these holes:
import diplib as dip
import math
# Load image and set pixel size
img = dip.ImageRead('N6uqw.jpg')
img.SetPixelSize(0.042, "mm")
# Extract object
obj = ~dip.Threshold(dip.Gauss(img))[0]
obj = dip.EdgeObjectsRemove(obj)
# Remove noise
obj = dip.Opening(dip.Closing(obj,9),9)
# Measure object area
lab = dip.Label(obj)
msr = dip.MeasurementTool.Measure(lab,img,['Size'])
objectArea = msr[1]['Size'][0]
# Measure holes
obj = dip.EdgeObjectsRemove(~obj)
lab = dip.Label(obj)
msr = dip.MeasurementTool.Measure(lab,img,['Size'])
sz = msr['Size']
holeAreas = []
for ii in sz.Objects():
holeAreas.append(sz[ii][0])
# Add hole areas to main object area
objectArea += sum(holeAreas)
print('Object diameter = %f mm' % (2 * math.sqrt(objectArea / math.pi)))
for a in holeAreas:
print('Hole diameter = %f mm' % (2 * math.sqrt(a / math.pi)))
這給了我輸出:
Object diameter = 57.947768 mm
Hole diameter = 6.540086 mm
Hole diameter = 6.695357 mm
Hole diameter = 15.961935 mm
Hole diameter = 6.511002 mm
Hole diameter = 6.623011 mm
請注意,上面的代碼中有很多假設.還有一個問題是相機沒有正好位于物體上方,您可以看到孔的右側反射光.這肯定會增加這些測量的不精確性.但還要注意,我在測量物體時沒有使用物體是圓形的知識(僅在將面積轉換為直徑時).或許可以使用圓度標準來克服一些成像缺陷.
Note that there are a lot of assumptions in the code above. There is also an issue with the camera not being centered exactly above the object, you can see the right side of the holes reflecting light. This will certainly add imprecision to these measurements. But note also that I didn't use the knowledge that the object is round when measuring it (only when converting area to diameter). It might be possible to use the roundness criterion to overcome some of the imaging imperfections.
上面的代碼使用了 DIPlib,這是一個 C++ 庫,具有相當粗糙的 Python 接口.Python 語法是 C++ 語法的直接翻譯,有些東西還是很別扭和非 Pythonic.但它專門針對量化,因此我建議您在自己的應用程序中嘗試一下.
The code above uses DIPlib, a C++ library with a rather rough Python interface. The Python syntax is a direct translation of the C++ syntax, and some things are still quite awkward and non-Pythonic. But it is aimed specifically at quantification, and hence I recommend you try it out for your application.
這篇關于使用 Opencv python 進行精確測量的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!