全局变量
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);//闭操作,排除小型黑洞,使物体聚合
//轮廓查找 vector<vector<Point>>contours; vector<Vec4i>hierarchy; findContours(
imgcanny, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//drawContours(img, contours, -1, Scalar(0, 0, 255), 1, 8,hierarchy);//绘制全部轮廓
//轮廓筛选 vector<vector<Point>>finalcontours; vector<vector<Point>>contours_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) { vector<Point2f>maxcontours(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<double, int> reorder; reorder.insert(pair<double, int>(
maxcontours[0].x + maxcontours[0].y, 0)); reorder.insert(pair<double, int>(
maxcontours[1].x + maxcontours[1].y, 1)); reorder.insert(pair<double, int>(
maxcontours[2].x + maxcontours[2].y, 2)); reorder.insert(pair<double, int>(
maxcontours[3].x + maxcontours[3].y, 3)); int i = 0; Point2f srcimg[4]; for (map
<double, int>::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); //轮廓查找 vector<vector
<Point>>contours; vector<Vec4i>hierarchy; findContours(imgcanny, contours,
hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //drawContours(img, contours,
-1, Scalar(0, 0, 255), 1, 8,hierarchy);//绘制全部轮廓 //轮廓筛选 vector<vector<Point>>
finalcontours; vector<vector<Point>>contours_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; vector<Point2f>maxcontours(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<double, int> reorder; reorder.insert(pair<double, int>(
maxcontours[0].x + maxcontours[0].y, 0)); reorder.insert(pair<double, int>(
maxcontours[1].x + maxcontours[1].y, 1)); reorder.insert(pair<double, int>(
maxcontours[2].x + maxcontours[2].y, 2)); reorder.insert(pair<double, int>(
maxcontours[3].x + maxcontours[3].y, 3)); Point2f srcimg[4]; int i = 0; for (map
<double, int>::iterator iter = reorder.begin(); iter != reorder.end(); iter++) {
srcimg[i] = maxcontours[iter->second]; i++; } Mat dest = (Mat_<double>(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); } }
效果图