小案例:使用OpenCV數一數玉米粒的個數
阿新 • • 發佈:2022-03-09
一、概述
案例:給出一張玉米圖片數一數有多少玉米粒(ps:玉米粒之間有相互壓住的情況)
實現步驟:
1.輸入原圖
2.灰度影象
3.二值化(使用自動預值),黑白圖
4.使用心態學開操作進行降噪聲
5.對影象進行腐蝕,對白色區域進行儘可能隔離,為下一步距離變換做準備
6.執行距離變換
7.進行區域性二值化(將玉米粒隔離開)
8.進行膨脹操作消除黑色噪點
9.執行邊緣檢測
10.執行輪廓發現
11.繪製輪廓並得出輪廓個數,輪廓的個數就是玉米粒的個數。
12.結束
二、程式碼示例
src = imread(filePath);if(src.empty()){ cout << "影象資料為空"<<endl; return; } imshow("src",src); blur(src,src,Size(3,3),Point(-1,-1));//均值模糊去除一些噪聲 cvtColor(src,gray,COLOR_BGR2GRAY);//轉為灰度影象 //對影象進行二值分割,使用自動預值的方法 threshold(gray,gray,0,255,THRESH_BINARY_INV|THRESH_TRIANGLE); imshow("threshold",gray); //執行形態學開操作消除影象中的噪聲點 Mat kernel = getStructuringElement(MORPH_RECT,Size(5,5)); morphologyEx(gray,gray,MORPH_OPEN,kernel,Point(-1,-1),3);//2代表連續開操作兩次 imshow("morphologyEx",gray); //對影象進行腐蝕,為下一步距離變換做準備 erode(gray,gray,kernel,Point(-1,-1),3); imshow("erode",gray);//進行距離變換 distanceImage = Mat(gray.size(),CV_32FC1); distanceTransform(gray,distanceImage,DIST_L2,3); normalize(distanceImage,distanceImage,0,1,NORM_MINMAX);//歸一化處理 imshow("distanceTransForm",distanceImage); //區域性二值化 Mat dist_8u; distanceImage.convertTo(dist_8u,CV_8U); adaptiveThreshold(dist_8u,dist_8u,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY,85,0); imshow("thre",dist_8u); kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); //進一步膨脹,儘可能的消除黑色噪聲點 dilate(dist_8u, dist_8u, kernel, Point(-1, -1), 5); imshow("dist-binary", dist_8u); //邊緣檢測 Canny(dist_8u,dist_8u,0,255); //執行輪廓發現 vector<vector<Point>> contours; vector<Vec4i> hierarchy;//拓撲結構 Mat myResult = Mat::zeros(dist_8u.size(),CV_8UC3); findContours(dist_8u,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE); RNG rng(12345); for(size_t i =0;i<contours.size();i++){ //繪製輪廓 drawContours(myResult,contours,i,Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)),-1); } //輪廓計數 cout<< "number of:"<<contours.size()<<endl; imshow("result",myResult);
三、圖片演示