使用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); }
复制代码

 

 

三、图片示例

 

posted on   飘杨......  阅读(499)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2020-03-16 Handler、Looper、MessageQueue原理分析
2020-03-16 ThreadLocal原理分析
2014-03-16 java中使用阻塞队列实现生产这与消费这之间的关系
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示