一、简介
二、轮廓最小外接矩形的绘制
#include "opencv2/opencv.hpp"
using namespace cv;
void main()
{
//轮廓最小外接矩形的绘制
Mat srcImg = imread("E://00.png");
Mat dstImg = srcImg.clone();
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, , , CV_THRESH_BINARY); //二值化
imshow("threshold", srcImg);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
vector<Rect> boundRect(contours.size()); //定义外接矩形集合
vector<RotatedRect> box(contours.size()); //定义最小外接矩形集合
Point2f rect[];
for(int i=; i<contours.size(); i++)
{
box[i] = minAreaRect(Mat(contours[i])); //计算每个轮廓最小外接矩形
boundRect[i] = boundingRect(Mat(contours[i]));
circle(dstImg, Point(box[i].center.x, box[i].center.y), , Scalar(, , ), -, ); //绘制最小外接矩形的中心点
box[i].points(rect); //把最小外接矩形四个端点复制给rect数组
rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(, , ), , );
for(int j=; j<; j++)
{
line(dstImg, rect[j], rect[(j+)%], Scalar(, , ), , ); //绘制最小外接矩形每条边
}
}
imshow("dst", dstImg);
waitKey();
}
三、粗略计算物体像素长宽
#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv;
void main()
{
Mat srcImg = imread("E://cup.jpg");
imshow("src", srcImg);
Mat dstImg = srcImg.clone();
medianBlur(srcImg, srcImg, );
GaussianBlur(srcImg, srcImg, Size(, ), , );
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, , , CV_THRESH_BINARY_INV); //INV是因为背景白色,物体黑色,需要反转一下
imshow("threshold", srcImg);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
cout<<"num="<<contours.size()<<endl;
vector<Rect> boundRect(contours.size());
vector<RotatedRect> box(contours.size());
Point2f rect[];
for(int i=; i<contours.size(); i++)
{
box[i] = minAreaRect(Mat(contours[i]));
boundRect[i] = boundingRect(Mat(contours[i]));
cout<<box[i].angle<<endl;
cout<<box[i].center<<endl;
cout<<box[i].size.width<<endl;
cout<<box[i].size.height<<endl;
circle(dstImg, Point(box[i].center.x, box[i].center.y), , Scalar(, , ), -, );
//绘制外接矩形和 最小外接矩形(for循环)
rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(, , ), , );
box[i].points(rect);//把最小外接矩形四个端点复制给rect数组
for(int j=; j<; j++)
{
line(dstImg, rect[j], rect[(j+)%], Scalar(, , ), , );
}
char width[], height[];
sprintf(width, "width=%0.2f", box[i].size.width);
sprintf(height, "height=%0.2f", box[i].size.height);
putText(dstImg, width, Point(, ), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(, , ));
putText(dstImg, height, Point(, ), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(, , ));
}
imshow("dst", dstImg);
waitKey();
}
四、倾斜物体矫正提取
#include "opencv2/opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv;
void main()
{
Mat srcImg = imread("E://qrcode.jpg");
imshow("src", srcImg);
Mat dstImg = srcImg.clone();
GaussianBlur(srcImg, srcImg, Size(, ), , );
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
Canny(srcImg, srcImg, , );//因为原图比较复杂,所以需要将canny的值调大,去除不想要的成分
//threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY_INV); //二值化也可以实现canny效果,不过在本例中杂絮较多
imshow("canny", srcImg);
Mat element = getStructuringElement(MORPH_RECT, Size(, ), Point(-, -)); //定义结构元素
dilate(srcImg, srcImg, element); //膨胀
imshow("dilate", srcImg);
erode(srcImg, srcImg, element);
imshow("erode", srcImg);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
vector<Rect> boundRect(contours.size());
vector<RotatedRect> box(contours.size());
Point2f rect[];
for(int i=; i<contours.size(); i++)
{
box[i] = minAreaRect(Mat(contours[i]));
boundRect[i] = boundingRect(Mat(contours[i]));
if(box[i].size.width < || box[i].size.height<)//筛选
continue;
rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(, , ), , );
circle(dstImg, Point(box[i].center.x, box[i].center.y), , Scalar(, , ), -, );
box[i].points(rect);
for(int j=; j<; j++)
{
line(dstImg, rect[j], rect[(j+)%], Scalar(, , ), , );
}
float angle;
cout<<"angle="<<box[i].angle<<endl;
angle = box[i].angle;
char width[], height[];
sprintf(width, "width=%0.2f", box[i].size.width);
sprintf(height, "height=%0.2f", box[i].size.height);
putText(dstImg, width, Point(, ), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(, , ));
putText(dstImg, height, Point(, ), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(, , ));
imshow("temp", dstImg);
//利用仿射变换进行旋转 另一种方法,透视变换
if (< abs(angle) && abs(angle)<=)
angle = angle;//负数,顺时针旋转
else if (< abs(angle) && abs(angle)<)
angle = - abs(angle);//正数,逆时针旋转
Point2f center = box[i].center; //定义旋转中心坐标
double angle0 = angle;
double scale = ;
Mat roateM = getRotationMatrix2D(center, angle0, scale); //获得旋转矩阵,顺时针为负,逆时针为正
warpAffine(dstImg, dstImg, roateM, dstImg.size()); //仿射变换
//保存二维码
int x0=, y0=, w0=, h0=;
x0 = boundRect[i].x;
y0 = boundRect[i].y;
w0 = boundRect[i].width;
h0 = boundRect[i].height;
Mat ROI = dstImg(Rect(x0, y0, w0, h0));
imwrite("F://1.jpg", ROI);
}
imshow("dst", dstImg);
waitKey();
}