灰度图像导致 HoughCircles() 方法不准确
grayscale image causing inaccuracies in HoughCircles() method
这是 openCV polygon detection 的后续。对于第二张图片,我没有检测到任何矩形,但那是因为我的阈值对于该图片不正确。
我使用了 otsu 阈值,并添加了一个约束来删除检测到的小矩形和其他不相关的矩形。
import numpy as np
import cv2 as cv
import math
img = cv.imread("t1.jpeg")
n=0
#rectangle parameters
width=0
height=0
start_x=0
start_y=0
end_x=0
end_y=0
#houghcircles parameters
minr=0
maxr=0
mind=0
maxarea=0
area=0
output = img.copy()
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret2,th = cv.threshold(gray,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
#rectangle detection
contours, _ = cv.findContours(th, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
for contour in contours:
approx = cv.approxPolyDP(contour, 0.01* cv.arcLength(contour, True), True)
cv.drawContours(img, [approx], 0, (0, 0, 0), 5)
x = approx.ravel()[0]
y = approx.ravel()[1]
x1 ,y1, w, h = cv.boundingRect(approx)
a=w*h
if len(approx) == 4 and x>15 :
aspectRatio = float(w)/h
if aspectRatio >= 2.5 and a>50:
print(x1,y1,w,h)
width=w
height=h
start_x=x1
start_y=y1
end_x=start_x+width
end_y=start_y+height
cv.rectangle(output, (start_x,start_y), (end_x,end_y), (0,0,255),3)
cv.putText(output, "rectangle "+str(x1)+" , " +str(y1-5), (x1, y1-5), cv.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
minr=int(17*width/192)
maxr=int(7*width/64)
mind=int(width//5)
print("start",start_x,start_y)
print("width",width)
print("height",height)
print("minr", minr)
print("maxr",maxr)
print("mind",mind)
cv.imshow("op1",output)
#circle detection,converting binary to decimal.
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, mind,param1=50, param2=20, minRadius=minr, maxRadius=maxr)
detected_circles = np.uint16(np.around(circles))
for (x, y ,r) in detected_circles[0, :]:
if(y>start_y and x>start_x and y<start_y+height and x<start_x+width):
cf= ((x-start_x)*8)/width
fp= cf-math.floor(cf)
if(fp>0.50):
idx=math.ceil(cf)
else:
idx=math.floor(cf)
exp=int(4- (0.5* (idx+1)))
n+= 2**exp
print("circle",x,y,r)
cv.circle(output, (x, y), r, (0, 0, 0), 3)
cv.circle(output, (x, y), 2, (0, 255, 255), 3)
print(n)
cv.imshow("th",th)
cv.imshow("gray",gray)
cv.imshow('output',output)
cv.waitKey(0)
cv.destroyAllWindows()
最终结果是这样的:
现在矩形检测成功了,但是圆形检测不正确。检测到的圆与目标圆的大小大致相同,这意味着 HoughCircles() 的参数是正确的,尽管未在正确的位置检测到圆。
这可能是因为眩光导致圆圈在灰度图像中几乎消失(我在 HoughCircles() 方法中使用):
如何使用此图像的 HoughCircles() 方法?
编辑:修复了代码中的一个小错误。问题仍然存在,但是我用其他图像进行了测试,并且它适用于灰度图像足够好的图像:
这是在 Python/OpenCV 中提取圆的一种方法。转换为LAB,分离B通道,然后在黑圈上做阈值。
输入:
import cv2
import numpy as np
# load images
img = cv2.imread('4_sign.jpg')
# convert to LAB
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
# separate B channel
b = lab[:,:,2]
# threshold and invert
thresh = cv2.threshold(b, 105, 255, cv2.THRESH_BINARY)[1]
thresh = 255 - thresh
# apply morphology to clean it up
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# get min enclosing circle
# numpy points are (y,x), so need to transpose
points = np.argwhere(morph.transpose()>0)
center, radius = cv2.minEnclosingCircle(points)
print('center:', center, 'radius:', radius)
# draw circle on copy of input
result = img.copy()
cx = int(round(center[0]))
cy = int(round(center[1]))
rr = int(round(radius))
cv2.circle(result, (cx,cy), rr, (255,255,255), 2)
# save output
cv2.imwrite('4_sign_circle.jpg', result)
# display results
cv2.imshow('thresh',thresh)
cv2.imshow('morph',morph)
cv2.imshow('result',result)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
加法
这是一个使用 HoughCircles 的版本。
import cv2
import numpy as np
# load images
img = cv2.imread('4_sign.jpg')
ht, wd = img.shape[:2]
minhw = min(ht,wd)
# convert to LAB
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
# separate B channel
b = lab[:,:,2]
# threshold and invert
thresh = cv2.threshold(b, 105, 255, cv2.THRESH_BINARY)[1]
thresh = 255 - thresh
# apply morphology to clean it up
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# get circle from HoughCircles
min_dist = int(minhw/20)
circles = cv2.HoughCircles(morph, cv2.HOUGH_GRADIENT, 1, minDist=min_dist, param1=100, param2=10, minRadius=30, maxRadius=60)
#print(circles)
result = img.copy()
for circle in circles[0]:
# draw the circle on copy of input
(x,y,r) = circle
center = (x,y)
radius = r
print('center:', center, 'radius:', radius)
x = int(x)
y = int(y)
cv2.circle(result, center, radius, (255, 255, 255), 2)
# save output
cv2.imwrite('4_sign_circle2.jpg', result)
# display results
cv2.imshow('thresh',thresh)
cv2.imshow('morph',morph)
cv2.imshow('result',result)
cv2.waitKey(0)
结果:
文字信息:
center: (410.5, 686.5) radius: 54.4
这是 openCV polygon detection 的后续。对于第二张图片,我没有检测到任何矩形,但那是因为我的阈值对于该图片不正确。
我使用了 otsu 阈值,并添加了一个约束来删除检测到的小矩形和其他不相关的矩形。
import numpy as np
import cv2 as cv
import math
img = cv.imread("t1.jpeg")
n=0
#rectangle parameters
width=0
height=0
start_x=0
start_y=0
end_x=0
end_y=0
#houghcircles parameters
minr=0
maxr=0
mind=0
maxarea=0
area=0
output = img.copy()
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret2,th = cv.threshold(gray,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
#rectangle detection
contours, _ = cv.findContours(th, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
for contour in contours:
approx = cv.approxPolyDP(contour, 0.01* cv.arcLength(contour, True), True)
cv.drawContours(img, [approx], 0, (0, 0, 0), 5)
x = approx.ravel()[0]
y = approx.ravel()[1]
x1 ,y1, w, h = cv.boundingRect(approx)
a=w*h
if len(approx) == 4 and x>15 :
aspectRatio = float(w)/h
if aspectRatio >= 2.5 and a>50:
print(x1,y1,w,h)
width=w
height=h
start_x=x1
start_y=y1
end_x=start_x+width
end_y=start_y+height
cv.rectangle(output, (start_x,start_y), (end_x,end_y), (0,0,255),3)
cv.putText(output, "rectangle "+str(x1)+" , " +str(y1-5), (x1, y1-5), cv.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
minr=int(17*width/192)
maxr=int(7*width/64)
mind=int(width//5)
print("start",start_x,start_y)
print("width",width)
print("height",height)
print("minr", minr)
print("maxr",maxr)
print("mind",mind)
cv.imshow("op1",output)
#circle detection,converting binary to decimal.
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, mind,param1=50, param2=20, minRadius=minr, maxRadius=maxr)
detected_circles = np.uint16(np.around(circles))
for (x, y ,r) in detected_circles[0, :]:
if(y>start_y and x>start_x and y<start_y+height and x<start_x+width):
cf= ((x-start_x)*8)/width
fp= cf-math.floor(cf)
if(fp>0.50):
idx=math.ceil(cf)
else:
idx=math.floor(cf)
exp=int(4- (0.5* (idx+1)))
n+= 2**exp
print("circle",x,y,r)
cv.circle(output, (x, y), r, (0, 0, 0), 3)
cv.circle(output, (x, y), 2, (0, 255, 255), 3)
print(n)
cv.imshow("th",th)
cv.imshow("gray",gray)
cv.imshow('output',output)
cv.waitKey(0)
cv.destroyAllWindows()
最终结果是这样的:
现在矩形检测成功了,但是圆形检测不正确。检测到的圆与目标圆的大小大致相同,这意味着 HoughCircles() 的参数是正确的,尽管未在正确的位置检测到圆。
这可能是因为眩光导致圆圈在灰度图像中几乎消失(我在 HoughCircles() 方法中使用):
如何使用此图像的 HoughCircles() 方法?
编辑:修复了代码中的一个小错误。问题仍然存在,但是我用其他图像进行了测试,并且它适用于灰度图像足够好的图像:
这是在 Python/OpenCV 中提取圆的一种方法。转换为LAB,分离B通道,然后在黑圈上做阈值。
输入:
import cv2
import numpy as np
# load images
img = cv2.imread('4_sign.jpg')
# convert to LAB
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
# separate B channel
b = lab[:,:,2]
# threshold and invert
thresh = cv2.threshold(b, 105, 255, cv2.THRESH_BINARY)[1]
thresh = 255 - thresh
# apply morphology to clean it up
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# get min enclosing circle
# numpy points are (y,x), so need to transpose
points = np.argwhere(morph.transpose()>0)
center, radius = cv2.minEnclosingCircle(points)
print('center:', center, 'radius:', radius)
# draw circle on copy of input
result = img.copy()
cx = int(round(center[0]))
cy = int(round(center[1]))
rr = int(round(radius))
cv2.circle(result, (cx,cy), rr, (255,255,255), 2)
# save output
cv2.imwrite('4_sign_circle.jpg', result)
# display results
cv2.imshow('thresh',thresh)
cv2.imshow('morph',morph)
cv2.imshow('result',result)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
加法
这是一个使用 HoughCircles 的版本。
import cv2
import numpy as np
# load images
img = cv2.imread('4_sign.jpg')
ht, wd = img.shape[:2]
minhw = min(ht,wd)
# convert to LAB
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
# separate B channel
b = lab[:,:,2]
# threshold and invert
thresh = cv2.threshold(b, 105, 255, cv2.THRESH_BINARY)[1]
thresh = 255 - thresh
# apply morphology to clean it up
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# get circle from HoughCircles
min_dist = int(minhw/20)
circles = cv2.HoughCircles(morph, cv2.HOUGH_GRADIENT, 1, minDist=min_dist, param1=100, param2=10, minRadius=30, maxRadius=60)
#print(circles)
result = img.copy()
for circle in circles[0]:
# draw the circle on copy of input
(x,y,r) = circle
center = (x,y)
radius = r
print('center:', center, 'radius:', radius)
x = int(x)
y = int(y)
cv2.circle(result, center, radius, (255, 255, 255), 2)
# save output
cv2.imwrite('4_sign_circle2.jpg', result)
# display results
cv2.imshow('thresh',thresh)
cv2.imshow('morph',morph)
cv2.imshow('result',result)
cv2.waitKey(0)
结果:
文字信息:
center: (410.5, 686.5) radius: 54.4