opencv图片旋转90°/-90°/180°,转一条博客

本文介绍了使用OpenCV实现图像旋转的方法。通过transpose()和flip()函数,可实现图像的90°和180°旋转。如顺时针90°旋转用transpose(src,tmp) + flip(tmp,dst,1),逆时针90°旋转用transpose(src,tmp) + flip(tmp,dst,0),180°旋转直接用flip(src,dst,-1)。

 

偶然间看到大佬博客:https://blog.youkuaiyun.com/fengbingchun/article/details/52554711

用到2个函数:

 transpose(Mat src,Mat &dst);     //转置

flip(Mat src,Mat &dst,int nFlag) ;     //镜像

 

测试代码:

    Mat src = imread("E:/TestImg/t1.jpg");
    Mat temp,dst0,dst1,dst_1;
    transpose(src, temp);
    flip(temp,dst1,1);
    flip(temp,dst0,0);
    flip(temp, dst_1, -1);
    imshow("src",src);
    imshow("transpose",temp);
    imshow("flip:1",dst1);
    imshow("flip:0", dst0);
    imshow("flip:-1", dst_1);
    waitKey();
运行截图:

观测结果可以发现:

 transpose()之后,图片做了90°转置,并且左右镜像了

再flip(),第3个参数为0时,图像摆正,相当于逆时针旋转了90°

 

2.当图像需要旋转90°时,flip()第3个参数为1:

    Mat src = imread("E:/TestImg/t1.jpg");
    Mat temp,dst;
    transpose(src, temp);
    flip(temp,dst,1);
    imshow("src",src);
    imshow("transpose",temp);
    imshow("flip:1",dst);
    waitKey();
结果:

3.当图像需要180°旋转时:

    Mat src = imread("E:/TestImg/t1.jpg");
    Mat temp,dst;
    flip(src,dst,-1);
    imshow("src",src);
    imshow("flip: -1",dst);
结果:

当然,180°旋转用remap()也可以实现,稍微麻烦了一点

 

总结一下:

需顺时针90°旋转时,transpose(src,tmp) + flip(tmp,dst,1)

需逆时针90°旋转时,transpose(src,tmp) + flip(tmp,dst,0)

需180°旋转时,直接flip(src,dst,-1)
--------------------- 
作者:andylan_zy 
来源:优快云 
原文:https://blog.youkuaiyun.com/andylanzhiyong/article/details/84857915 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

<think>我们面对的问题是如何在C#中使用OpenCVSharp库实现图片的自动旋转矫正。根据引用[1]和引用[2]提供的线索,我们可以利用霍夫变换检测直线,然后通过统计直线角度来确定旋转角度,进而实现旋转矫正。 步骤概述: 1. 读取图像并换为灰度图。 2. 边缘检测(如Canny)以获取图像的边缘。 3. 使用霍夫变换检测直线。 4. 统计检测到的直线角度,并选择代表性角度(如中值或众数)。 5. 根据得到的角度进行旋转矫正。 注意:由于图像中的直线可能包含水平线和垂直线,我们需要根据实际需求调整角度。通常,我们期望将文本行矫正为水平,因此我们关注接近水平或垂直的直线(但主要关注水平直线)。在实际操作中,我们可能只考虑角度在某一范围内的直线(例如,-45°到45°之间的直线,因为超过45°的直线更接近垂直,对水平矫正意义不大)。 然而,引用[2]中提到,使用中值角度可能更准确,因为可以排除极端值的影响。另外,也可以考虑使用直方图统计出现频率最高的角度范围。 具体实现步骤: 1. 读取图像 2. 换为灰度图像 3. 边缘检测(Canny) 4. 霍夫直线检测 5. 计算每条直线的角度(注意:霍夫检测返回的是线段的两个端点,我们可以通过计算线段与水平方向的夹角得到角度,然后换为角度值) 6. 筛选角度(例如,只保留角度在-45°到45°之间的直线) 7. 计算这些角度的中值(或者使用直方图统计,取频率最高的角度范围的平均值) 8. 根据这个角度进行旋转矫正 注意:旋转角度应该是负值(因为我们需要反向旋转来矫正)或者根据旋转方向调整。 旋转函数:使用OpenCvSharp中的Cv2.WarpAffine进行旋转。 下面我们用代码实现:</think>在 C# 中使用 OpenCVSharp 实现图片自动旋转矫正,主要通过检测图像中的直线并计算代表性角度来实现。以下是完整实现步骤: ### 实现步骤 1. **读取图像并预处理** ```csharp using OpenCvSharp; Mat src = Cv2.Imread("input.jpg", ImreadModes.Color); Mat gray = new Mat(); Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY); Cv2.GaussianBlur(gray, gray, new Size(5, 5), 0); ``` 2. **边缘检测与直线检测** ```csharp Mat edges = new Mat(); Cv2.Canny(gray, edges, 50, 150); // 边缘检测 LineSegmentPoint[] lines = Cv2.HoughLinesP( edges, 1, Math.PI / 180, 100, minLineLength: 100, maxLineGap: 10 ); ``` 3. **计算直线角度并筛选** ```csharp List<double> angles = new List<double>(); foreach (var line in lines) { double angle = Math.Atan2(line.P2.Y - line.P1.Y, line.P2.X - line.P1.X) * 180 / Math.PI; // 筛选接近水平/垂直的直线(排除45°以上斜线) if (Math.Abs(angle) < 45) angles.Add(angle); } ``` 4. **确定旋转角度(关键步骤)** ```csharp // 方法1:取角度中位数(抗干扰性强) angles.Sort(); double medianAngle = angles[angles.Count / 2]; // 方法2:直方图统计(更精确) var angleGroups = angles.GroupBy(a => (int)a / 5 * 5); // 5°分组 double maxFreqAngle = angleGroups.OrderByDescending(g => g.Count()).First().Key; ``` 5. **执行旋转矫正** ```csharp Point2f center = new Point2f(src.Width / 2f, src.Height / 2f); Mat rotMat = Cv2.GetRotationMatrix2D(center, medianAngle, 1.0); Mat dst = new Mat(); Cv2.WarpAffine(src, dst, rotMat, src.Size(), InterpolationFlags.Cubic, BorderTypes.Reflect101); ``` 6. **保存结果** ```csharp Cv2.ImWrite("output.jpg", dst); ``` ### 关键优化点 1. **角度筛选**:通过`if (Math.Abs(angle) < 45)`过滤无效斜线,提高文本/表格类图像的矫正精度 2. **中值抗干扰**:使用中位数而非平均值,避免离群值影响(如`[0°, 5°, 25°, 150°]`取中值25°) 3. **边缘增强**:可在Canny前使用`Cv2.EqualizeHist()`增强低对比度图像 4. **旋转填充**:添加`BorderTypes.Constant`参数避免黑色边框 > 实际效果:该方法对文档、表格等含直线特征的图像矫正准确率可达90%以上,但对无规则自然场景效果有限[^1][^2]。 ### 完整示例代码 ```csharp using OpenCvSharp; using System.Collections.Generic; using System.Linq; class ImageRotator { static void Main() { Mat src = Cv2.Imread("skewed_document.jpg"); // 1. 灰度化+边缘检测 Mat gray = src.CvtColor(ColorConversionCodes.BGR2GRAY); Mat edges = gray.Canny(50, 150); // 2. 直线检测 var lines = Cv2.HoughLinesP(edges, 1, Math.PI/180, 100, 100, 10); // 3. 角度计算与筛选 var angles = new List<double>(); foreach (var line in lines) { double angle = Math.Atan2(line.P2.Y - line.P1.Y, line.P2.X - line.P1.X) * 180 / Math.PI; if (Math.Abs(angle) < 45) angles.Add(angle); } // 4. 取中值角度 angles.Sort(); double rotAngle = angles.Count > 0 ? angles[angles.Count / 2] : 0; // 5. 旋转矫正 Point2f center = new Point2f(src.Width/2f, src.Height/2f); Mat rotMat = Cv2.GetRotationMatrix2D(center, rotAngle, 1.0); Mat dst = new Mat(); Cv2.WarpAffine(src, dst, rotMat, src.Size()); Cv2.ImWrite("corrected.jpg", dst); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值