說明
1、MinAreaRect()函數可以尋找最小外接矩形;返回一個旋轉矩形,旋轉矩形的旋轉角度一定是負(angle < 0),表示逆時針旋轉,順時針爲正;
2、最小外接矩形可以用來進行矩形的旋轉校正(應用);
Code
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);
}
}
}
效果
1、旋轉矩形
2、測量物體的像素寬高:
3、二維碼旋轉校正: