1、MinAreaRect()函数可以寻找最小外接矩形;返回一个旋转矩形,旋转矩形的旋转角度一定是负(angle < 0),表示逆时针旋转,顺时针为正;
2、最小外接矩形可以用来进行矩形的旋转校正(应用);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Util;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using System.Drawing;
namespace lesson25
{
class Program
{
static void Main(string[] args)
{
//旋转矩形
//Mat src = CvInvoke.Imread("mask2.jpg");
//Mat dst = src.Clone();
//Mat grayimg = new Mat();
//CvInvoke.Imshow("input", src);
//CvInvoke.CvtColor(src, grayimg, ColorConversion.Bgr2Gray);
//CvInvoke.Threshold(grayimg, grayimg, 100, 255, ThresholdType.Binary);
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy = new VectorOfRect();
//CvInvoke.FindContours(grayimg, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
//CvInvoke.DrawContours(dst, contours, -1, new MCvScalar(255, 255, 0), 2);
//for (int i = 0; i < contours.Size; i++)
//{
// RotatedRect rotatedRect = CvInvoke.MinAreaRect(contours[i]); //计算最小外接矩形
// PointF[] pointFs = new PointF[4]; //存储旋转矩形的4个顶点
// pointFs = rotatedRect.GetVertices();
// CvInvoke.PutText(dst, "rotated rectangle", new Point((int)pointFs[1].X, (int)pointFs[1].Y), FontFace.HersheyDuplex,
// 1.2, new MCvScalar(0, 0, 255), 2);
// for (int j = 0; j < 4; j++)
// {
// CvInvoke.Line(dst, new Point((int)pointFs[j].X, (int)pointFs[j].Y), new Point((int)pointFs[(j + 1) % 4].X, (int)pointFs[(j + 1) % 4].Y),
// new MCvScalar(0, 0, 255), 2);
// }
//}
//CvInvoke.Imshow("result", dst);
//CvInvoke.WaitKey(0);
///测量物体宽高
//Mat src = CvInvoke.Imread("cup.jpg");
//Mat dst = src.Clone();
//Mat grayImg = new Mat();
//CvInvoke.Imshow("input", src);
//CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
//CvInvoke.Threshold(grayImg, grayImg, 100, 255, ThresholdType.BinaryInv);
//CvInvoke.Imshow("binary image", grayImg);
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy = new VectorOfRect();
//CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxNone);
//CvInvoke.DrawContours(dst, contours, -1, new MCvScalar(0, 255, 0), 3);
//for(int i = 0; i < contours.Size;i++)
//{
// RotatedRect rotatedRect = CvInvoke.MinAreaRect(contours[i]);
// Rectangle rectangle = CvInvoke.BoundingRectangle(contours[i]);
// CvInvoke.Rectangle(dst, rectangle, new MCvScalar(255, 255, 0), 2);
// PointF[] pFs = new PointF[4];
// pFs = rotatedRect.GetVertices();
// for(int j = 0; j < 4; j++)
// {
// CvInvoke.Line(dst, new Point((int)pFs[j].X, (int)pFs[j].Y), new Point((int)pFs[(j + 1) % 4].X, (int)pFs[(j + 1) % 4].Y),
// new MCvScalar(0, 0, 255), 2);
// }
// string strwidth = String.Format("Width = {0:N2}.", rotatedRect.Size.Width);
// string strheight = String.Format("Height = {0:N2}.", rotatedRect.Size.Height);
// CvInvoke.PutText(dst, strwidth, new Point(rectangle.X, rectangle.Y - 25), FontFace.HersheyComplexSmall,
// 1.2, new MCvScalar(0, 255, 0), 2);
// CvInvoke.PutText(dst, strheight, new Point(rectangle.X, rectangle.Y - 2), FontFace.HersheyComplexSmall,
// 1.2, new MCvScalar(0, 255, 0), 2);
//}
//CvInvoke.Imshow("result", dst);
//CvInvoke.WaitKey(0);
///二维码选装校正
Mat src = CvInvoke.Imread("qrcode.jpg");
Mat dst = src.Clone();
Mat result = new Mat();
CvInvoke.Imshow("input", src);
Mat grayImg = new Mat();
CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
CvInvoke.AdaptiveThreshold(grayImg, grayImg, 255, AdaptiveThresholdType.GaussianC, ThresholdType.BinaryInv, 11, 5);
CvInvoke.MedianBlur(grayImg, grayImg, 5);
CvInvoke.Imshow("binary", grayImg);
Mat kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(11, 11), new Point(-1, -1));
Mat kerne2 = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));
CvInvoke.Dilate(grayImg, grayImg, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar()); //膨胀连通区域
CvInvoke.Imshow("dilate", grayImg);
CvInvoke.Erode(grayImg, grayImg, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
CvInvoke.Imshow("erode", grayImg);
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
VectorOfRect hierarchy = new VectorOfRect();
CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxNone);
for(int i = 0; i < contours.Size; i++)
{
RotatedRect rotatedRect = CvInvoke.MinAreaRect(contours[i]);
PointF[] pFs = new PointF[4];
Mat rotateMat = new Mat();
double angle = 0.0; //度数
double rWidth = rotatedRect.Size.Width;
double rHeight = rotatedRect.Size.Height;
if(rWidth > 50 && rHeight > 50) //对轮廓进行筛选
{
pFs = rotatedRect.GetVertices();
Point[] pTs = new Point[4];
angle = rotatedRect.Angle;
for(int j = 0; j < 4;j++)
{
pTs[j].X = (int)pFs[j].X;
pTs[j].Y = (int)pFs[j].Y;
}
CvInvoke.Polylines(dst, pTs, true, new MCvScalar(0, 0, 255), 2); //绘制闭合多边形
if(0 < Math.Abs(angle) && Math.Abs(angle) <= 45) //逆时针
{
angle = angle;
}
else if(45 < Math.Abs(angle) && Math.Abs(angle) < 90) //顺时针
{
angle = 90 - Math.Abs(angle);
}
CvInvoke.GetRotationMatrix2D(rotatedRect.Center, angle, 1.0, rotateMat); //获取旋转矩阵
CvInvoke.WarpAffine(src, result, rotateMat, src.Size); //进行仿射变换
CvInvoke.Imshow("result111", result);
}
}
CvInvoke.Imshow("result", dst);
CvInvoke.WaitKey(0);
}
}
}