引言
在机器视觉中,有时需要对产品进行检测和计数。其难点无非是对于产品的图像分割。
由于之前网购的维生素片,有时候忘了今天有没有吃过,就想对瓶子里的药片计数...在学习opencv以后,希望实现对于维生素片分割计数算法。本次实战在基于形态学的基础上又衍生出基于距离变换的分水岭算法,使其实现的效果更具普遍性。
基于形态学的维生素片检测和计数
整体思路:
- 读取图片
- 形态学处理(在二值化前进行适度形态学处理,效果俱佳)
- 二值化
- 提取轮廓(进行药片分割)
- 获取轮廓索引,并筛选所需要的轮廓
- 画出轮廓,显示计数
opencv实现:
int main(int argc, char** argv) { Mat src, src_binary,dst,src_distance; src = imread("D:/opencv练习图片/维生素片机器视觉检测和计数.png"); imshow("原图片", src); Mat kernel = getStructuringElement(MORPH_RECT, Size(16, 16), Point(-1, -1)); morphologyEx(src, dst, MORPH_OPEN, kernel); imshow("形态学",dst); cvtColor(dst, dst, COLOR_RGB2GRAY); threshold(dst, src_binary, 100, 255, THRESH_OTSU); imshow("二值化", src_binary); vector<vector<Point>> contours; findContours(src_binary, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0)); RNG rng(12345); double area; Point2i PL; for (size_t i = 0; i < contours.size(); i++) { area = contourArea(contours[i]); if (area < 500)continue; PL = contours[i].front(); Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); drawContours(src, contours, i, color, 2, 8); putText(src, to_string(i), PL, FONT_HERSHEY_COMPLEX, 1, color, 2); } imshow("计数结果", src); waitKey(0); return 0; }
效果展示:
由上图可以看的,原图在经过形态学处理后,可以去除很多细节,简化后续的药片分割操作。
但是在计数结果图上发现,索引17号药片并没有完全分割(实际上修改形态学的结构元素尺寸(改为20*20)也可以完全分离这两个药片)。