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);
}
}
效果图