Opencv实践项目之实时物体的测量——c++

【Opencv实践项目之实时物体的测量——c++】Opencv实践项目之实时物体的测量——c++
文章图片

全局变量

Mat matrix; Point2f center; Mat frame; float scale = 0.25; bool flag = false;

主函数
int main() { frame = imread("celiang.jpg"); resize(frame, frame, Size(0,0), scale, scale, INTER_LINEAR); imshow("original", frame); int thres[] = { 50,255 }; Mat out; Point2f a4; getcontours(frame, thres,out,a4); //A4纸的长度为210,宽度为297 double a4_width = 210; double a4_height = 297; int scale = 3; Point2f mart; int th[] = { 50,255 }; getcontours_2(out, th,mart); if (flag) { int wid = round(mart.x / a4.x * a4_width); int hei = round(mart.y / a4.y * a4_height); string w = to_string(wid)+"cm"; putText(out, w, Point(center.x, center.y - 50), FONT_HERSHEY_SCRIPT_COMPLEX, 1, Scalar(0, 0, 255), 1); string h = to_string(hei)+"cm"; putText(out, h, Point(center.x - 70, center.y + hei ), FONT_HERSHEY_SCRIPT_COMPLEX, 1, Scalar(0, 0, 255), 1); } imshow("test", out); waitKey(0); return 0; }

参照物识别
void getcontours(Mat img, const int arr[],Mat& out,Point2f& ob,int minarea=1000*scale) { Mat imggray; cvtColor(img,imggray, COLOR_BGR2GRAY); Mat imggauss; GaussianBlur(imggray,imggauss, Size(5, 5), 1); Mat imgcanny; Canny(imggauss, imgcanny, arr[0], arr[1]); Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); morphologyEx(imgcanny, imgcanny, MORPH_CLOSE, kernel); //闭操作,排除小型黑洞,使物体聚合 //轮廓查找 vectorcontours; vectorhierarchy; findContours(imgcanny, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //drawContours(img, contours, -1, Scalar(0, 0, 255), 1, 8,hierarchy); //绘制全部轮廓 //轮廓筛选 vectorfinalcontours; vectorcontours_poly(contours.size()); for (int i = 0; i < contours.size(); i++) { if (contourArea(contours[i]) > minarea) { //approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); finalcontours.push_back(contours[i]); } } //drawContours(img, finalcontours, -1, Scalar(0, 0, 255), 1, 8); //找到最大轮廓 double len = INT_MIN; int index; for (int i = 0; i < finalcontours.size(); i++){ double l = arcLength(finalcontours[i], true); if ( l> len){len = l; } index = i; } if (finalcontours.size() != 0) { vectormaxcontours(finalcontours[index].size()); approxPolyDP(Mat(finalcontours[index]), maxcontours, 0.02*arcLength(finalcontours[index], true), true); //可通过修改近似曲线的阈值来 //最小外接矩形 RotatedRect bbox = minAreaRect(maxcontours); //得到长和宽 ob.x = bbox.size.width; ob.y = bbox.size.height; //为四个点排序 map reorder; reorder.insert(pair(maxcontours[0].x + maxcontours[0].y, 0)); reorder.insert(pair(maxcontours[1].x + maxcontours[1].y, 1)); reorder.insert(pair(maxcontours[2].x + maxcontours[2].y, 2)); reorder.insert(pair(maxcontours[3].x + maxcontours[3].y, 3)); int i = 0; Point2f srcimg[4]; for (map::iterator iter = reorder.begin(); iter != reorder.end(); iter++) { srcimg[i] = maxcontours[iter->second]; i++; } const Point2f dstimg[4] = { Point2f(0, 0),Point2f(bbox.size.width, 0) , Point2f(0, bbox.size.height),Point2f(bbox.size.width, bbox.size.height) }; matrix = getPerspectiveTransform(srcimg, dstimg); inv_matrix = matrix.inv(); Mat imgwarp; warpPerspective(img, imgwarp, matrix, Size(bbox.size.width, bbox.size.height)); out = imgwarp.clone(); } }

目标识别
void getcontours_2(Mat& img, const int arr[], Point2f& mart,int minarea = 1000*scale) { flag = false; Mat imggray; cvtColor(img, imggray, COLOR_BGR2GRAY); Mat imggauss; GaussianBlur(imggray, imggauss, Size(5, 5), 1); Mat imgcanny; Canny(imggauss, imgcanny, arr[0], arr[1]); //膨胀和腐蚀,闭操作,排除小型黑洞,使物体聚合 //开操作,消除小连接或者毛刺,在纤细处分离物体 Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); morphologyEx(imgcanny, imgcanny, MORPH_CLOSE, kernel); //轮廓查找 vectorcontours; vectorhierarchy; findContours(imgcanny, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //drawContours(img, contours, -1, Scalar(0, 0, 255), 1, 8,hierarchy); //绘制全部轮廓 //轮廓筛选 vectorfinalcontours; vectorcontours_poly(contours.size()); for (int i = 0; i < contours.size(); i++) { if (contourArea(contours[i]) > minarea&&contours[i].size()>500*scale) { //approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); finalcontours.push_back(contours[i]); } } //drawContours(img, finalcontours, -1, Scalar(0, 0, 255), 1, 8); //找到最大轮廓 double len = INT_MIN; int index; for (int i = 0; i < finalcontours.size(); i++) { double l = arcLength(finalcontours[i], true); if (l> len) { len = l; } index = i; } if (finalcontours.size() != 0) { flag = true; vectormaxcontours(finalcontours[index].size()); approxPolyDP(Mat(finalcontours[index]), maxcontours, 0.02*arcLength(finalcontours[index], true), true); //可通过修改近似曲线的阈值来//最小外接矩形 RotatedRect bbox = minAreaRect(maxcontours); //得到长和宽 mart.x = bbox.size.width; mart.y = bbox.size.height; //为四个点排序 map reorder; reorder.insert(pair(maxcontours[0].x + maxcontours[0].y, 0)); reorder.insert(pair(maxcontours[1].x + maxcontours[1].y, 1)); reorder.insert(pair(maxcontours[2].x + maxcontours[2].y, 2)); reorder.insert(pair(maxcontours[3].x + maxcontours[3].y, 3)); Point2f srcimg[4]; int i = 0; for (map::iterator iter = reorder.begin(); iter != reorder.end(); iter++) { srcimg[i] = maxcontours[iter->second]; i++; }Mat dest = (Mat_(3, 3) << srcimg[0].x, srcimg[0].y, 1, srcimg[1].x, srcimg[1].y, 1, srcimg[2].x, srcimg[2].y, 1); Mat original = dest*inv_matrix; center = srcimg[0]; arrowedLine(img, srcimg[0], srcimg[1], Scalar(0, 0, 255), 3, 8, 0); arrowedLine(img, srcimg[0], srcimg[2], Scalar(0, 0, 255), 3, 8, 0); } }

效果图

    推荐阅读