(1): coins.png
1.采用OpenCv中cv2.cvtColor()函数将coins.png图片进行灰度处理,得到coins_gray:
coins_gray = cv2.cvtColor(coins, cv2.COLOR_RGB2GRAY)
2.采用OpenCv中cv2.threshold()函数,带cv2.THRESH_OTSU(OTSU阈值法)参数,自适应对coins_gray阈值进行处理,获取二元值的灰度图像 :
ret,thresh=cv2.threshold(coins_gray,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
3.之后再轮廓检测:
cnts=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]
其中参数CV_RETR_EXTERNAL表示:只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略;参数CV_CHAIN_APPROX_SIMPLE表示:仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内(也就是第二个返回值),拐点与拐点之间直线段上的信息点不予保留;
4.计数提取出的边缘数即为硬币数,用循环将边缘的位置标在原图上画出并显示,记的数字显示在title中:
for i, contour in enumerate(cnts):
cv2.drawContours(coins, cnts, -1, (0, 0, 255), 1)
cv2.imshow(str(len(cnts))+(" coins"), coins)
cv2.imwrite("coins_result.jpg", coins)
其结果如下图1-1所示(左上角为其个数):
完整Python代码如下所示:
import cv2
coins = cv2.imread('coins.png')
coins_gray = cv2.cvtColor(coins, cv2.COLOR_RGB2GRAY)
ret, thresh = cv2.threshold(coins_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
for i, contour in enumerate(cnts):
cv2.drawContours(coins, cnts, -1, (0, 0, 255), 1)
cv2.imshow(str(len(cnts))+(" coins"), coins)
cv2.imwrite("coins_result.jpg", coins)
cv2.waitKey(0)
cv2.destroyAllWindows()
(2):Dowels.tiff
最开始想用霍夫变换对其进行圆形检测,由于效果不好这里换另外一种方案,仍然对其进行基本的图像操作之后二值化图像,检测轮廓。对Dowels.tiff的分割与记数原理与coins.png的原理类似,不同之处在于对其进行mean-shift(均值漂移)滤波。之后进行灰度变换、阈值分割、检测轮廓,最后对其计数并显示出来。
其结果如下图1-2所示(左上角为其个数):
完整Python代码如下所示:
import cv2
Dowels = cv2.imread('Dowels.tif')
cv2.imshow("Dowels_origin", Dowels)
# 进行mean—shift滤波
mean_shift_Dowels= cv2.pyrMeanShiftFiltering(Dowels, sp=10, sr=100)
gray = cv2.cvtColor(mean_shift_Dowels, cv2.COLOR_RGB2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[1]
for i, contour in enumerate(cnts):
cv2.drawContours(Dowels, cnts, i, (0, 0, 255), 1)
cv2.imshow(str(len(cnts)) + " Dowels", Dowels)
cv2.imwrite("Dowels_result.jpg", Dowels)
cv2.waitKey(0)
cv2.destroyAllWindows()
(3): rice.png
对rice.png的分割与记数原理与coins.png的原理类似,主要不同在于图像存在噪声的干扰,需要将其进行一下滤波处理。先将其转化为灰度图像,再对其进行滤波处理,之后对其进行自适应阈值分割,利用cv2.findContours()函数寻找轮廓,最后对其记数,并展示出来。
其结果如下图1-3所示(左上角为其个数):
完整Python代码如下所示:
from numpy import *
import cv2
rice = cv2.imread('rice.png')
rice_gray = cv2.cvtColor(rice, cv2.COLOR_RGB2GRAY)
# rice_gray_Blur = cv2.GaussianBlur(rice_gray,(5,5),1)
# rice_gray_Blur = box = cv2.boxFilter(rice_gray,-1,(3,3), normalize=False)
rice_gray_Blur = cv2.blur(rice_gray, (3, 3))
ret,thresh=cv2.threshold(rice_gray_Blur.copy(), 1,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
for i, contour in enumerate(cnts):
cv2.drawContours(rice, cnts, i, (0, 0, 255), 1)
cv2.imshow(str(len(cnts))+ " rice", rice)
cv2.waitKey(0)
cv2.destroyAllWindows()
完整实验代码,公众号后台回复:数字图像作业二。
我的微信公众号名称:深度学习与先进智能决策
微信公众号ID:MultiAgent1024
公众号介绍:主要研究分享深度学习、机器博弈、强化学习等相关内容!期待您的关注,欢迎一起学习交流进步!