100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 识别硬币和细胞数量+条形码检测(python+opencv)

识别硬币和细胞数量+条形码检测(python+opencv)

时间:2021-08-17 05:10:17

相关推荐

识别硬币和细胞数量+条形码检测(python+opencv)

如愿

一、准备工作二、硬币和细胞数量识别三、条形码定位和识别四、总结五、参考资料

一、准备工作

所用图片

python版本以及opencv版本

python 3.8.12 opencv 3.4.11

二、硬币和细胞数量识别

原理
用opencv读取图片,读取之后并进行灰度化和二值化二值化之后存储图片的二维列表里的值全为0和1,进行膨胀和腐蚀等操作使图像的轮廓更明显较为明显之后使用findContours,发现的轮廓数就是我们要求的数量
开始代码操作,导入库并定义文件路径

#导入相关包import cv2import numpy as npimport os#定义文件路径source_path='..\\source\\AI_digital_image\\'cell_file="cell.png"coin_file="coin.png"

构建完整路径并读取图片,图片我就不放了,自己运行看看就知道了,算了图片还是放代码后面,自己看看

#得到完整路径cell_path=source_path+cell_filecoin_path=source_path+coin_file #读取文件cell_read=cv2.imread(cell_path)coin_read=cv2.imread(coin_path)cv2.imshow("cell",cell_read)cv2.waitKey(0)

先进行细胞数量提取,这里进行了灰度化,而且手动调了一波亮度,因为这张图片上下的亮度不一致,不调整的话二值化得出来的效果不太好

#进行灰度化cell_gauss=cv2.GaussianBlur(cell_read,(5,5),0)#高斯降噪cell_gray=cv2.cvtColor(cell_gauss,cv2.COLOR_BGR2GRAY)#灰度化cell_att=cell_graycv2.waitKey(0)#上半部分亮度太低,手动增加for j in range(3,342):low=int(sum(cell_gray[j]))high=int(sum(cell_gray[335]))add=(high-low)/len(cell_read[3])for i in range(len(cell_read[3])):if int(cell_att[j][i])+add>255:cell_att[j][i]=255else :cell_att[j][i]+=addcv2.imshow("cell",cell_att)cv2.waitKey(0)

二值化

thre,cell_bw=cv2.threshold(cell_att,170,255,cv2.THRESH_BINARY_INV)#二值化cv2.imshow("cell",cell_bw)cv2.waitKey(0)

细胞的图片感觉应该是血液的样本,不然为啥这么多血红细胞,血红细胞中间是空的,灰度化之后会有小空洞,先用闭运算来填补这些空的地方

#闭运算,填充空洞#构造一个全1的5*5的矩阵kernel=np.ones((3,3),int)#设置形态学操作卷积的大小cell_close=cv2.morphologyEx(cell_bw,cv2.MORPH_CLOSE,kernel)cv2.imshow("cell",cell_close)cv2.waitKey(0)

开运算作用:用来消除小的物体,平滑形状边界,并且不改变其面积。可以去除小颗粒噪声,断开物体间的粘连

#开运算#构造一个全1的5*5的矩阵kernel=np.ones((11,11),int)#设置形态学操作卷积的大小cell_open=cv2.morphologyEx(cell_close,cv2.MORPH_OPEN,kernel)cv2.imshow("cell",cell_open)cv2.waitKey(0)

开运算之后再进行腐蚀,将两个细胞之间的间隔再拉大一点,同时把那些重叠的地方再细化

#腐蚀运算#构造一个全1的5*5的矩阵kernel=np.ones((20,20),int)#设置形态学操作卷积的大小cell_corr=cv2.erode(cell_open,kernel,iterations=1)cv2.imshow("cell",cell_corr)cv2.waitKey(0)

再进行开运算,把细化的重叠部分也断掉

#开运算#构造一个全1的5*5的矩阵kernel=np.ones((10,10),int)#设置形态学操作卷积的大小cell_close2=cv2.morphologyEx(cell_corr,cv2.MORPH_OPEN,kernel)cv2.imshow("cell",cell_close2)cv2.waitKey(0)

利用opencv的findcontours获取轮廓,返回的cell_count就是轮廓的数组,长度就是细胞的数量,只要求求数量,绘图时的轮廓就偷懒了,表示个意思就行

image,cell_count,hir=cv2.findContours(cell_close2,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)#检测所有轮廓,所有轮廓建立一个等级树结构。print(len(cell_count))cell_read=cv2.imread(cell_path)result = cv2.drawContours(cell_read, cell_count, -1 ,(0, 255, 0), 1)cv2.imshow('I',result)cv2.waitKey(0)

接下来就是硬币数量检测了,这个简单多了,刚刚读取了,这里进行灰度化和二值化

#进行灰度化和二值化coin_gauss=cv2.GaussianBlur(coin_read,(5,5),0)#高斯降噪coin_gray=cv2.cvtColor(coin_gauss,cv2.COLOR_BGR2GRAY)#灰度化thre,coin_bw=cv2.threshold(coin_gray,150,255,cv2.THRESH_BINARY_INV)#二值化cv2.imshow("coin",coin_bw)cv2.waitKey(0)

开始以为还要一次开运算,这里直接腐蚀效果就很好了

#腐蚀运算#构造一个全1的5*5的矩阵kernel=np.ones((20,20),int)#设置形态学操作卷积的大小coin_corr=cv2.erode(coin_bw,kernel,iterations=1)cv2.imshow("cell",coin_corr)cv2.waitKey(0)

获取数量

image,coin_count,hir=cv2.findContours(coin_corr,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)#检测所有轮廓,所有轮廓建立一个等级树结构。print(len(coin_count))coin_read=cv2.imread(coin_path)result = cv2.drawContours(coin_read, coin_count, -1 ,(0, 255, 0), 1)cv2.imshow('I',result)cv2.waitKey(0)

三、条形码定位和识别

定位就不调用库了,用opencv实现

#导入库import cv2

读取文件

bar_code_path='..\\source\\picture\\bar_code\\code_bar.jpg'bar_code=cv2.imread(bar_code_path)bar_code=cv2.resize(bar_code,(500,300))cv2.imshow('src',bar_code)cv2.waitKey(0)

转化为灰度图

#转化为灰度图bar_code_gray=cv2.cvtColor(bar_code,cv2.COLOR_BGR2GRAY)cv2.imshow('gray',bar_code_gray)cv2.waitKey(0)

高斯平滑滤波

# 高斯平滑滤波bar_code_gauss=cv2.GaussianBlur(bar_code_gray,(3,3),0)cv2.imshow('gauss',bar_code_gauss)cv2.waitKey(0)

求水平和垂直的梯度差,使用sobel算子,这里好像直接相减有些问题,可能是opencv在python里的存储类型和在c++里不一样,小于0的话就变成200+了

#求水平方向和垂直方向的梯度差,使用sobel算子bar_code_h=cv2.Sobel(bar_code_gauss,cv2.CV_64F,1,0,ksize=3,scale=1,delta=0,borderType=4)bar_code_v=cv2.Sobel(bar_code_gauss,cv2.CV_64F,0,1,ksize=3,scale=1,delta=0,borderType=4)#从16位转化为8位bar_code_x=cv2.convertScaleAbs(bar_code_h,alpha=1,beta=0)bar_code_y=cv2.convertScaleAbs(bar_code_v,alpha=1,beta=0)bar_code_xy=bar_code_xfor i in range(len(bar_code_x)):for j in range(len(bar_code_x[0])):if int(bar_code_x[i][j])-(bar_code_y[i][j])>=0:bar_code_xy[i][j]=bar_code_x[i][j]-bar_code_y[i][j]else:bar_code_xy[i][j]=0cv2.imshow('x',bar_code_x)cv2.waitKey(0)cv2.imshow('y',bar_code_y)cv2.waitKey(0)cv2.imshow('xy',bar_code_xy)cv2.waitKey(0)

均值滤波

#均值滤波bar_code_blur=cv2.blur(bar_code_xy,(3,3))cv2.imshow('blur',bar_code_blur)cv2.waitKey(0)

二值化

#二值化thr,bar_code_th=cv2.threshold(bar_code_blur,170,255,cv2.THRESH_BINARY)cv2.imshow('threshold',bar_code_th)cv2.waitKey(0)

闭运算,填充条形码间隙

#闭运算,填充条形码间隙import numpy as npkernel=np.ones((7,7),int)#设置形态学操作卷积的大小bar_code_close=cv2.morphologyEx(bar_code_th,cv2.MORPH_CLOSE,kernel)cv2.imshow('close',bar_code_close)cv2.waitKey(0)

腐蚀,消除旁边的小白点

#腐蚀kernel=np.ones((7,7),int)#设置形态学操作卷积的大小bar_code_ero=cv2.erode(bar_code_close,kernel)cv2.imshow('erode',bar_code_ero)cv2.waitKey(0)

膨胀使条码连起来

#膨胀bar_code_dia=cv2.dilate(bar_code_ero,kernel)bar_code_dia=cv2.dilate(bar_code_dia,kernel)bar_code_dia=cv2.dilate(bar_code_dia,kernel)bar_code_dia=cv2.dilate(bar_code_dia,kernel)cv2.imshow('dilate',bar_code_dia)cv2.waitKey(0)

定位,这偏差有点迷,可能使计算梯度差时造成的

image,barcode,hir=cv2.findContours(bar_code_dia,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)#检测所有轮廓,所有轮廓建立一个等级树结构。barcode_read=cv2.imread(bar_code_path)result = cv2.drawContours(barcode_read, barcode, -1 ,(0, 255, 0), 1)cv2.imshow('I',result)cv2.waitKey(0)

识别条形码的话可以自己手动排查,也可以调用库,这里就偷懒一下,调用pyzbar库实现

#调用条码库进行条码识别import pyzbar.pyzbar as pyzbarimport cv2bar_code_path='..\\source\\picture\\bar_code\\code_bar.jpg'srcImg = cv2.imread(bar_code_path)cv2.imshow("Image", srcImg)barcodes = pyzbar.decode(srcImg)for barcode in barcodes:barcodeData = barcode.data.decode("utf-8")print(barcodeData)cv2.waitKey(0)

四、总结

经过上面这些例子,大概明白了对图像的操作都是提取出需要的元素,然后简化简化再简化,最后变为0和1,而0和1对应的就是黑和白,就十分方便处理

五、参考资料

Opencv:10个步骤检测出图片中条形码

python-opencv检测图片中鸡蛋个数/数量

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。