使用OpenCV对图像进行切边
一、概述
案例:使用OpenCV对旋转图片及正常图片进行切边。
A:对正常图片切边的步骤
1.加载图像
2.对图像进行灰度化
3.边缘检测
4.轮廓发现
5.找出符合目标的最大外接矩形,并使用矩形的四个坐标点绘制线
6.根据找到Rect在原图上切除ROI区域
7.显示ROI区域
B:对旋转图像切边的步骤
1.加载原图
2.对图像进行灰度化
3.边缘检测
4.轮廓发现
5.找出图像旋转角度(a.找出旋转矩形的最大宽和最大高 b.找出这个目标矩形的旋转角度及旋转矩形。c.把此矩形绘制出来)
6.根据图片中心点及旋转角度,利用getRotationMatrix2D制作目标旋转Mat
7.利用wrapAffine+第6步的旋转矩阵实现最终的旋转
8.此时的图片为正确的旋转图片,可以利用“A:对正常图片切边”的步骤来实现图片的切边
二、代码示例
/*将旋转图片转成正常图片*/
void CaseOneEdgeCutting::correctImageAngle(Mat & target){ src = imread(filePath.toStdString().c_str()); if(src.empty()){ qDebug()<<"加载图片异常"; return; } imshow("src",src); //降噪 cvtColor(src,gray,COLOR_BGR2GRAY); imshow("gray",gray); //边缘检测 Canny(gray,gray,threshold_value,threshold_value*2); imshow("canny",gray); //轮廓发现 vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(gray,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE); Mat resultImage = Mat::zeros(src.size(),CV_8UC3); float width = 0; float height = 0; RNG rng(12345); float degree = 0; for(size_t t =0;t<contours.size();t++){//找到角度 RotatedRect minRect = minAreaRect(contours[t]); degree = abs(minRect.angle); if(degree>0){ width = max(width,minRect.size.width); height = max(height,minRect.size.height); } } for(size_t t = 0;t<contours.size();t++){ RotatedRect minRect = minAreaRect(contours[t]); if (width == minRect.size.width && height == minRect.size.height) { degree = minRect.angle; qDebug()<<"degree:"<<degree; Point2f pts[4]; minRect.points(pts); Scalar color = Scalar(0,0,255); for(int i=0;i<4;i++){ line(resultImage,pts[i], pts[(i + 1)%4], color, 2, 8, 0); } } } imshow("result1",resultImage); Point2f center(src.cols/2,src.rows/2);//图片中心点 Mat degreeRoi = getRotationMatrix2D(center,-degree,1); warpAffine(src,target,degreeRoi,src.size(),INTER_LINEAR, 0, Scalar(255, 255, 255)); imshow("dst",target); } /*正常图片找到ROI区域*/ void CaseOneEdgeCutting::findEdgeCuttingROIImage(Mat &target){ Mat srcTarget = target.clone(); //降噪 cvtColor(target,target,COLOR_BGR2GRAY); //边缘检测 Canny(target,target,threshold_value,threshold_value*2); imshow("target",target); //轮廓发现 vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(target,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE); Mat resultImage = Mat::zeros(src.size(),CV_8UC3); float width = target.cols*0.5; float height = target.rows*0.5; RNG rng(12345); Rect box; for(size_t t = 0;t<contours.size();t++){ RotatedRect minRect = minAreaRect(contours[t]); if(minRect.size.width>width&&minRect.size.height>height&&minRect.size.width<(src.cols-60)){ qDebug()<<"执行到了这里"; Point2f pts[4]; minRect.points(pts); box = minRect.boundingRect(); Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)); for(int i=0;i<4;i++){ line(resultImage,pts[i], pts[(i + 1)%4], color, 2, 8, 0); } } } imshow("result2",resultImage); // //绘制roi区域 Mat roiImage = srcTarget(box); imshow("roiImage",roiImage); }
三、图片示例
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2020-03-16 Handler、Looper、MessageQueue原理分析
2020-03-16 ThreadLocal原理分析
2014-03-16 java中使用阻塞队列实现生产这与消费这之间的关系