我用了cv.HoughCircles函数,但不会选择合适的参数,效果不好。
原图:
{
```
```import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
if img.ndim == 2:
plt.imshow(img,cmap='gray')
else:
plt.imshow(cv.cvtColor(img,cv.COLOR_BGR2RGB))
plt.show()
img=cv.imread('C:/Users/1/Desktop/img/test.jpg')
gray=cv.cvtColor(img, cv.COLOR_BGR2GRAY)
dst = cv.equalizeHist(gray)#应用直方图均衡化
gaussian = cv.GaussianBlur(dst,(9,9),0)
#利用Canny进行边缘检测
GrayImage = cv.Canny(gaussian, 20,180, apertureSize=3)
ret, th1 = cv.threshold(GrayImage, 127, 255, cv.THRESH_TOZERO) # 固定阈值二值化
th2 = cv.adaptiveThreshold(th1, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 3, 5)
th3 = cv.adaptiveThreshold(th2, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 5)
kernel = np.ones((6, 9), np.uint8)
erosion = cv.erode(th3, kernel, iterations=1) # 腐蚀处理
dilation = cv.dilate(erosion, kernel, iterations=1) # 膨胀处理
imgray = cv.Canny(erosion, 3, 8) # Canny算子边缘检测
circles = cv.HoughCircles(imgray, cv.HOUGH_GRADIENT, 1, 40, param1=100, param2=6, minRadius=8,maxRadius=10)
circles = np.uint16(np.around(circles))
P = circles[0] # 去掉circles数组一层外括号
for i in P:
cv.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 5)
cv.circle(img, (i[0], i[1]), 5, (0, 0, 255), 3)
show(img)
}
我参考了一些博主的文章,链接:https://blog.csdn.net/SouthWooden/article/details/98741985
废话不多说,直接上代码
import cv2
import numpy as np
def cv_show(neme, img):
cv2.imshow(neme, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
image = cv2.imread('1.jpg')
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Canny 边缘检测(图像、min值、max值)
edges = cv2.Canny(img, 7, 12)
ret, thresh1 = cv2.threshold(edges, 127, 255, cv2.THRESH_BINARY)
# 膨胀操作
kernel1 = np.ones((5, 5), np.uint8)
# 换个封装函数,膨胀 当前载入 腐蚀后--膨胀
erosion = cv2.dilate(thresh1, kernel1, iterations=1)
kernel = np.ones((3, 3))
# 腐蚀操作
sb = cv2.erode(erosion, kernel, iterations=1)
cv_show("s", thresh1)
cv_show("name", erosion)
cv_show('sda', sb)
# 轮廓查询
contours, hierarchy = cv2.findContours(sb, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
# 轮廓外接圆
(x, y), radius = cv2.minEnclosingCircle(contours[i])
center = (int(x), int(y))
radius = int(radius)
# 轮廓区域
# 轮廓面积
area = cv2.contourArea(contours[i])
if 300 <= area < 2000:
image = cv2.circle(image, center, radius, (0, 0, 255), 1)
cv_show('sad', image)
可以检测圆,后边有说明。
import cv2
import numpy as np
__author__ = "boboa"
def detect_circles_demo(image):
dst = cv2.pyrMeanShiftFiltering(image, 10, 100) # 均值偏移滤波
cimage = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(cimage, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=40, minRadius=0, maxRadius=0)
# 整数化,#把circles包含的圆心和半径的值变成整数
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
# 画出外边圆
cv2.circle(image, (i[0], i[1]), i[2], (0, 255, 0), 2)
# 画出圆心
cv2.circle(image, (i[0], i[1]), 2, (0, 0, 255), 3)
cv2.imshow("circles", image)
if __name__ == "__main__":
img = cv2.imread("image/circles.jpg")
cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
cv2.imshow("input image", img)
detect_circles_demo(img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.HoughCircles(image, method, dp, minDist, circles, param1, param2, minRadius, maxRadius)
参数:
image:输入图像,必须是灰度图像
method:检测方法,常用CV_HOUGH_GRADIENT
dp:检测内侧圆心的累加器图像的分辨率于输入图像之比的倒数,如dp=1,累加器和输入图像具有相同的分辨率,如果dp=2,累计器便有输入图像一半那么大的宽度和高度
minDist: 两个圆心之间的最小距离
param1: 是method方法的参数,在CV_HOUGH_GRADIENT表示传入canny边缘检测的阈值
param2:对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值
它越小,就越可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了
minRadius:默认值0,圆半径的最小值
maxRadius:默认值0,圆半径的最大值
cv2.circle是画圆函数(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img
参数:img:源图像
center:圆心坐标
radius:圆的半径
color:设定圆的颜色
thickness:如果是正数,表示圆轮廓的粗细程度。如果是负数,表示要绘制实心圆
lineType:圆线条的类型
shift:圆心坐标和半径值中的小数位数
图像中的圆直径基本一致,比较好处理。
(1)检查一下 固定阈值二值化 的参数"127"是否合适,在该语句后显示一下二值化图像即可;
(2)主要是 HoughCircles 中的最大、最小半径 minRadius、maxRadius 参数设置是否合适
从运行结果来看设置的小了,可以适当增大,保证要找的圆的半径值在 minRadius、maxRadius 之间。