【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);
}
}
效果图
推荐阅读
- YOLOv5|基于改进YOLOv5轻量化的烟火检测
- YOLOv7|YOLOv7 训练报错 IndexError: list index out of range
- #|AI-无损检测方向速读(基于深度学习的表面缺陷检测方法综述)
- 工业缺陷检测|工业产品表面缺陷检测方法——综述
- 目标检测|研究一下带旋转的目标检测工作
- 深度学习|【Yolov5在‘Segmentation-Based-Surface-Defect-Detection’上的验证】
- #|YOLOv6 | 模型结构与训练策略详细解析
- #|YOLOv5的Tricks | 【Trick14】YOLOv5的val.py脚本的解析
- 目标检测|yolov5