【发布时间】:2020-09-08 11:54:31
【问题描述】:
我是图像处理和边缘检测的新手,所以希望你们能帮助我对 opencv python 有所了解。免责声明:这是一个工作项目。
这是一个关于 houghcircles、轮廓和图像处理的 3 部分问题。完整的代码将在这面文字墙的末尾。
A 部分,考虑一下image AA。对于此图像,阈值处理很容易,可以仅隔离大外圆和两个内圆。有了这个,很容易使用霍夫圈来找到圆圈。但是,我从来没有调整过包含 dp、minDist、param1、param2、minRad 和 maxRad 的 Hough Circle 函数以适用于不同的图像。我使用只有 2 个参数的 Hough 函数,虽然它运行良好,但我觉得我没有利用该函数的全部功能。它足够强大,可以在其他 image BB 上工作,但在 image CC 上表现不佳。相同的参数可以得到 2/3 圈正确。所以我的问题是,调整霍夫圆函数以获得一组可以正常工作的参数的方法是什么?我是否必须强行使用它并继续手动调整,直到找到有效的方法?有没有办法告诉霍夫圆只在左侧区域找到圆而忽略其他所有内容?
B 部分,我知道如果不知道最小和最大半径 (HoughCircles can't detect circles on this image),Hough Circles 会有一些限制,并且要让一组参数适用于所有这些将是困难的。这就是为什么我考虑改用 Contours 的原因。据我了解,轮廓仅适用于黑色的白色边缘图像。因此,将图像处理为只有白色边缘是很重要的。我的问题是轮廓似乎是have trouble separating the two inner circle as two separate circle,而white image threshold seems to be touching。我应该如何解决这个问题来优化轮廓以检测两个单独的圆圈而不是将它们组合为一个?
C 部分,到目前为止我提供的图像是内圈比大外圈更亮的最佳情况。假设现在我有不同的图像image DD 和image EE。现在对该图像进行阈值化以仅隔离内圈要困难得多。我现有的 A 部分和 B 部分代码都不起作用。看来我需要更多地处理图像。我尝试了adaptivethreshold、dilate、erode、canny、opening、close、gradient的方法,但我仍然无法让它按预期工作。实际上,我最接近让它工作的是当我尝试 179 块大小和 5 c 的自适应阈值以及 6 次迭代的侵蚀和扩张时。有了这个,我可以找到圆圈但不准确。所以我希望就我需要哪种类型的图像处理或者我应该只拍摄更好的图像来获得建议。
现在这是我使用的代码。感谢您花时间阅读我的问题,我希望你们能帮助我解决这个问题。
import numpy as np
import cv2
# https://stackoverflow.com/questions/28327020/opencv-detect-mouse-position-clicking-over-a-picture
def onMouse(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
print('x = %d, y = %d'%(x, y))
def createCircle(img,out,dp,minDist):
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, dp, minDist)
if circles is not None:
circles = np.round(circles[0, :]).astype("int") #convert the (x, y) coordinates and radius of the circles to integers
for (x, y, r) in circles:
cv2.circle(out, (x, y), r, (0, 255, 0), 4) # draw the circle in the output image
return x, y ,r
def createCircle2(img,out,dp,minDist,param1,param2,minRad,maxRad):
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, dp, minDist,param1,param2,minRad,maxRad)
if circles is not None:
circles = np.round(circles[0, :]).astype("int") #convert the (x, y) coordinates and radius of the circles to integers
for (x, y, r) in circles:
cv2.circle(out, (x, y), r, (0, 255, 0), 4) # draw the circle in the output image
return x, y, r
def showImage(name,img,sizescale):
if sizescale == 1:
cv2.imshow("%s"%name, img)
else:
cv2.imshow("%s"%name, cv2.resize(img,(0,0),fx=sizescale,fy=sizescale))
cv2.setMouseCallback("%s"%name, onMouse) # enable coordinate function
cv2.waitKey(0) # wait infinitely
cv2.destroyAllWindows() # destroy window once any key is pressed
#inner brighter (PART A and B)
img = "AA.jpg"
# img = "BB.jpg"
# img = "CC.jpg"
#inner darker (PART C)
# img = "DD.jpg"
# img = "EE.jpg"
scale = 0.3 # resize images
sigma = 0.33 # best according to link below regarding image_median
cv2.destroyAllWindows()
image = cv2.imread(img)
output1 = image.copy()
output2 = image.copy()
output3 = image.copy()
kernel = np.ones((3,3), np.uint8)
########################################################################################## HOUGH CIRCLES (PART A)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(image_gray, (5, 5),20)
image_median = np.median(blur)
#https://stackoverflow.com/questions/41893029/opencv-canny-edge-detection-not-working-properly
if image_median > 191: #light image
canny_lower = int(max(0, (1.0 - 2*sigma) * (255-image_median)))
canny_upper = int(min(255, (1.0 + 2*sigma) * (255-image_median)))
elif image_median > 127:
canny_lower = int(max(0, (1.0 - sigma) * (255-image_median)))
canny_upper = int(min(255, (1.0 + sigma) * (255-image_median)))
elif image_median < 63: # dark image
canny_lower = int(max(0, (1.0 - 2*sigma) * image_median))
canny_upper = int(min(255, (1.0 + 2*sigma) * image_median))
else:
canny_lower = int(max(0, (1.0 - sigma) * image_median))
canny_upper = int(min(255, (1.0 + sigma) * image_median))
# print(image_median,canny_lower,canny_upper)
ret, thresh1 = cv2.threshold(blur,15, 255, cv2.THRESH_BINARY) # for outer big circle
ret2, thresh2= cv2.threshold(blur, 0, 255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # for inner circles
canny = cv2.Canny(thresh2,canny_lower,canny_upper) # for inner circles
# showImage("thresh1", thresh1, scale)
# showImage("thresh2", thresh2, scale)
# showImage("canny", canny, scale)
createCircle(thresh1,output1,10,5000)
createCircle(thresh2,output1,10,10000)
createCircle(canny,output1,18,50000)
# createCircle2(opening,output1,10,10000,350,10,300,900)
# createCircle2(thresh3,output1,20,10000,300,10,200,500)
# createCircle2(canny,output1,50,50000,300,10,200,500)
showImage("output", output1, scale)
################################################################################################# CONTOURS (PART B)
ret3, thresh3 = cv2.threshold(blur,127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh3,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
cnt = contours
for i in range (len(cnt)):
(x,y),radius = cv2.minEnclosingCircle(cnt[i])
center = (int(x),int(y))
radius = int(radius)
if radius > 100 :
cv2.circle(output2,center,radius,(0,255,0),4)
print('Circle' + str(i) + ': Center =' + str(center) + 'Radius =' + str(radius))
# showImage("thresh3", thresh3, scale)
showImage("output2", output2, scale)
################################################################################################# CONTOURS (PART C)
bs = 179 #blocksize
c = 5 #c
thresh4 = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,bs,c)
ero_n = 6
dil_n = 6
erode = cv2.erode(thresh4, kernel, iterations=ero_n)
dilate = cv2.dilate(erode, kernel, iterations=dil_n)
contours2, hierarchy2 = cv2.findContours(dilate,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours2))
cnt2 = contours2
for i in range (len(cnt2)):
(x,y),radius = cv2.minEnclosingCircle(cnt2[i])
center = (int(x),int(y))
radius = int(radius)
if radius > 150 :
cv2.circle(output3,center,radius,(0,255,0),4)
print('Circle' + str(i) + ': Center =' + str(center) + 'Radius =' + str(radius))
showImage("output3", output3, scale)
【问题讨论】:
标签: python opencv edge-detection hough-transform opencv-contour