3

我是 OpenCV 和 python 的新手,所以请像 12 年级学生一样帮助我。我的问题是我想检测钻头的正确阈值或边缘以进行测量,但是我所做的在图像中产生了很多噪声,因此我无法找到对象的正确轮廓

我尝试去除图像中的眩光,然后进行直方图均衡,然后尝试自适应阈值。

gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h,s,v=cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))

bgi=cv2.GaussianBlur(gray, (3, 3), 1.0)
rn_gr = cv2.fastNlMeansDenoising(bgi,None,10,7,21)

equ = cv2.equalizeHist(rn_gr)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(rn_gr)

nonSat = s < 40
disk = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))    
nonSat = cv2.erode(nonSat.astype(np.uint8), disk) 
v2 = v.copy()    
v2[nonSat == 0] = 0;  
glare = v2 > 200;
glare = cv2.dilate(glare.astype(np.uint8), disk);
glare = cv2.dilate(glare.astype(np.uint8), disk);    
corrected = cv2.inpaint(img, glare, 5, cv2.INPAINT_NS)
object=corrected[485:1665,225:335]
gray_co=cv2.cvtColor(object, cv2.COLOR_BGR2GRAY)
bgi_co=cv2.GaussianBlur(gray_co, (3, 3), 1.0)
rn_gr_co = cv2.fastNlMeansDenoising(bgi_co,None,10,7,21)
cl2 = clahe.apply(rn_gr_co)

v=np.median(cl2)
lower=int(max(0,(1.0-sigma)*v))
upper=int(min(255,(1.0+sigma)*v))
print(lower,upper)
edged = cv2.Canny(cl2,lower,upper)
th3_o = cv2.adaptiveThreshold(obj,upper,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
        th3_o=~th3_o

#kernel = np.ones((5,5),np.uint8)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
morph = cv2.morphologyEx(th3_o, cv2.MORPH_GRADIENT, kernel)
closing = cv2.morphologyEx(th3_o, cv2.MORPH_CLOSE, kernel)
opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel)

contours_o, hierarchy = cv2.findContours(th3_o,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt_o in contours_o:
   epsilon = 0.1*cv2.arcLength(cnt_o,True)
   approx = cv2.approxPolyDP(cnt_o,epsilon,True)
   con_o = cv2.drawContours(th3_o, contours_o, -1, (0,255,0), 3)
plt.imshow(con_o)
plt.show()

我的预期结果应该看起来像我用边界所需图像绘制的图片,但我得到的是这样的不想要的图像

4

1 回答 1

4

我认为您使用了太多操作并且过度考虑了检测轮廓的方法。您在没有实现每一步的目标的情况下使用了太多的顺序操作。通常,对图像进行预处理以去除噪声或平滑图像(高斯/中值/双边模糊)。然后对图像进行某种二进制分割以隔离轮廓(阈值处理、Canny 边缘检测)。从这里,可以进行形态转换以进一步过滤或增强,例如腐蚀或膨胀。然后你可以找到轮廓并进行额外的过滤(轮廓面积、接近度、纵横比)。对于这个问题,我们的想法是通过战略方法保持简单,以便隔离外轮廓


这是一种潜在的方法

  • 转换为灰度和中值模糊图像以去除噪声和平滑图像
  • 阈值图像
  • 寻找轮廓
import cv2

image = cv2.imread('1.jpg')

blur = cv2.medianBlur(image, 7)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,160,255, cv2.THRESH_BINARY_INV)[1]

cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

for c in cnts:
    cv2.drawContours(image, [c], -1, (36, 255, 12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.imwrite('image.png', image)
cv2.waitKey()

于 2019-07-11T20:25:56.600 回答