最近有个项目需要做细孔定位和孔距测量,需要做边缘检测和轮廓提取,先看初步效果图:
主要实现代码:
int MainWindow::Test()
{// 2.9 单个像素长度um 5倍double dbUnit = 2.9/(1000*5);// 定义显示窗口namedWindow("src", WINDOW_NORMAL|WINDOW_KEEPRATIO);namedWindow("threshold", WINDOW_NORMAL|WINDOW_KEEPRATIO);namedWindow("morphologyEx x1", WINDOW_NORMAL|WINDOW_KEEPRATIO);namedWindow("morphologyEx x2", WINDOW_NORMAL|WINDOW_KEEPRATIO);namedWindow("canny", WINDOW_NORMAL|WINDOW_KEEPRATIO);namedWindow("dst", WINDOW_NORMAL|WINDOW_KEEPRATIO);resizeWindow("src", 1080,720);resizeWindow("threshold", 1080,720);resizeWindow("morphologyEx x1", 1080,720);resizeWindow("morphologyEx x2", 1080,720);resizeWindow("canny", 1080,720);resizeWindow("dst", 1080,720);//【1】载入图像Mat src = imread("0.28um+5x.jpg"); Mat src_clone = src.clone();if(src.empty()){qDebug()<<"图片为空";return 1;}imshow("src",src);//【2】转灰度图Mat gray;cvtColor(src,gray,COLOR_BGR2GRAY);//imshow("gray",gray);//【3】图像二值化threshold(gray,gray,130,190,THRESH_BINARY);imshow("threshold",gray);//【4】执行形态学开操作去除噪点Mat kernel = getStructuringElement(MORPH_RECT,Size(15,15),Point(-1,-1));morphologyEx(gray,gray,MORPH_CLOSE,kernel,Point(-1,-1),1);imshow("morphologyEx x1",gray);//【4】执行形态学开操作去除噪点Mat kernel1 = getStructuringElement(MORPH_RECT,Size(10,10),Point(-1,-1));morphologyEx(gray,gray,MORPH_CLOSE,kernel1,Point(-1,-1),1);imshow("morphologyEx x2",gray);//【5】边缘检测Canny(gray,gray,0,255);imshow("canny",gray);//【6】轮廓发现vector<vector<Point>> contours;vector<Vec4i> her;findContours(gray,contours,her,RETR_TREE,CHAIN_APPROX_SIMPLE);Mat srcImg = src;//拟合椭圆:fitEllipse()vector<RotatedRect> box(contours.size());Point2f rect[4];for (int i = 0; i<contours.size(); i++){Rect rect = boundingRect(contours[i]);Point2f pRadius;if(contours[i].size()>105){box[i] = fitEllipse(Mat(contours[i]));//条件过滤if( box[i].size.aspectRatio()<0.8||box[i].size.area()>10000000||rect.width<300 )continue;float majorAxis = std::max(box[i].size.width, box[i].size.height);rectangle(srcImg,rect,Scalar(0, 0, 255));ellipse(srcImg, box[i], Scalar(255, 0, 0), 1, 8);float x = rect.width/2.0;float y = rect.height/2.0;//【8】找出圆心并绘制pRadius=Point2f(rect.x+x,rect.y+y);cv::String det_info = cv::format("[%d] %.1f,%.1f(%dx%d),%.5f mm, %.5f mm",i,pRadius.x, pRadius.y, rect.width, rect.height,dbUnit*rect.width, dbUnit*majorAxis);cv::Point bbox_points;bbox_points = cv::Point(rect.x, rect.y);bbox_points = cv::Point(rect.x + det_info.size() * 11, rect.y);bbox_points = cv::Point(rect.x + det_info.size() * 11, rect.y - 15);bbox_points = cv::Point(rect.x, rect.y - 15);cv::putText(srcImg, det_info, bbox_points, cv::FONT_HERSHEY_DUPLEX, 0.4, cv::Scalar(255, 255, 255), 1, cv::LINE_AA);circle(srcImg,pRadius,1,Scalar(0,0,255),1);pRadius=box[i].center;circle(srcImg,pRadius,1,Scalar(255,0,0),1);}}// 绘制结果imshow("dst", srcImg);// 保存结果imwrite("dst.png", srcImg);
}