接上篇文章…
一般的,一个扫描的文件是不可能完完全全摆正了的。它多多少少会有些倾斜。
现在有如下图片:

它逆时针进行了旋转,那么想要把多余的白边去掉且摆正应该怎么做呢?
步骤如下:
1、边缘检测
2、找出轮廓
3、找出最小外接矩形,获得旋转的角度
4、根据旋转的角度进行仿射变换
5、按切边的操作进行

代码(没有用到的已注释):

#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>using namespace cv;
using namespace std;Mat src, dst, gray_src;int current_level = 50;
int max_level = 255;
void cut_image(int, void*);
void rotating_image(int, void*);const char* output_title = "rectminArea";
int main(int argc, char**argv)
{src = imread("D:/test/切边测试图-旋转.png", 1);if (src.empty()){cout << "图片未找到" << endl;return -1;}//namedWindow(output_title,CV_WINDOW_AUTOSIZE);//createTrackbar("Value", output_title, &current_level, max_level, cut_image);//cut_image(0,0);  //图像切边rotating_image(0,0); // 将图像旋转成正的imshow("input image", src);waitKey(0);return 0;}
//将图像旋转成正的
void rotating_image(int, void*)
{/*1、边缘检测2、找出轮廓3、找出最小外接矩形,获得旋转的角度4、仿射变换5、按切边的操作进行*/Mat canny_out;Canny(src, canny_out, current_level, 2 * current_level, 3, false);imshow("canny_out",canny_out);float minw = 0;float minh = 0;double angle = 0;vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(canny_out, contours,hierarchy, RETR_TREE,CHAIN_APPROX_SIMPLE, Point(0, 0));Mat showImg= Mat::zeros(src.size(), CV_8UC3);;RNG rng(12345);for (size_t t = 0; t < contours.size(); t++){RotatedRect minrect = minAreaRect(contours[t]);angle = minrect.angle;if (angle != 0)   {minh = max(minh,minrect.size.height);minw = max(minw,minrect.size.width);}}printf("minw:%f\n", minw);printf("minh:%f\n", minh);printf("angle:%f\n", angle);//值为负数,说明逆时针旋转,值为正数,说明顺时针旋转for (size_t t = 0; t < contours.size(); t++){RotatedRect minrect = minAreaRect(contours[t]);if (minrect.size.height== minh && minrect.size.width == minw){Point2f pts[4];minrect.points(pts);for (int i = 0; i < 4; i++){Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));line(showImg, pts[i], pts[(i + 1) % 4], color, 2, 8, 0);}}}imshow("showImg", showImg);Mat dst;Point2f center(src.cols/2, src.rows/2);Mat rota = getRotationMatrix2D(center, angle, 1.0);warpAffine(src, dst, rota, src.size(), INTER_LINEAR,0,Scalar(255,255,255));imshow("correct image",dst);//图像切边}//图像切边
void cut_image(int, void*)
{Mat canyImg;cvtColor(src, gray_src, CV_BGR2GRAY);Canny(gray_src, canyImg, current_level, 2 * current_level, 3,false);vector<vector<Point>> contours;vector<Vec4i>hierachy;Mat showImg = Mat::zeros(src.size(), CV_8UC3);findContours(canyImg, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));RNG rng(12345);int minw = src.cols*0.75;int minh = src.rows*0.75;Rect box; //获取roi区域Mat contoursimg= Mat::zeros(src.size(), CV_8UC3);for (size_t t = 0; t < contours.size(); t++){Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));drawContours(contoursimg, contours, int(t), color, 1, 8, hierachy, 0, Point(0, 0));RotatedRect minrect = minAreaRect(contours[t]); //获取轮廓的最小外接矩形float angle = abs(minrect.angle);if (minrect.size.height > minh && minrect.size.width > minw && minrect.size.width < (src.cols - 5)){Point2f pts[4];minrect.points(pts); //获取最小外接矩形的四个顶点坐标for(int i=0;i<4;i++){line(showImg,pts[i], pts[(i + 1) % 4], color, 2, 8, 0);cout << "X坐标:" << minrect.center.x <<" "<< "Y坐标:" << minrect.center.y << " "<<"偏移角度:" << angle << endl;}box = minrect.boundingRect();}if (box.width > 0 && box.height > 0){Mat roiImg=src(box);//截取roi区域imshow("roiImg", roiImg);}}imshow(output_title, showImg);imshow("contours image", contoursimg);}/* //做旋转图片的代码
int main() {Mat src = imread("D:/test/切边测试图.png");imshow("src", src);double angle = 45;Point2f center(src.cols / 2, src.rows / 2);Mat rot = getRotationMatrix2D(center, angle, 1);Rect bbox = RotatedRect(center, src.size(), angle).boundingRect();rot.at<double>(0, 2) += bbox.width / 2.0 - center.x;rot.at<double>(1, 2) += bbox.height / 2.0 - center.y;Mat dst;warpAffine(src, dst, rot, bbox.size(),1,0,Scalar(255,255,255));imshow("dst", dst);imwrite("D:/test/切边测试图-旋转.png",dst);waitKey(0);return 0;}
*/

运行结果:


由此可以知道,该图片旋转的角度是-45度,也就是逆时针旋转了45度。
那么就可以进行仿射变换:

Mat dst;Point2f center(src.cols/2, src.rows/2);Mat rota = getRotationMatrix2D(center, angle, 1.0);warpAffine(src, dst, rota, src.size(), INTER_LINEAR,0,Scalar(255,255,255));imshow("correct image",dst);

最终的结果是:

接下来就是切边的操作了,这里参考上一篇文章:
https://blog.csdn.net/Daker_Huang/article/details/85033368

OpenCv-C++-小案例实战-切边(二)相关推荐

  1. OpenCV C++案例实战十二《图像全景拼接》

    OpenCV C++案例实战十二<图像全景拼接> 前言 一.OpenCV Stitcher 1.功能源码 2.效果 二.图像全景拼接 1.特征检测 2.计算单应性矩阵 3.透视变换 4.图 ...

  2. python计算银行余额_Python 小案例实战 —— 简易银行存取款查询系统

    Python 小案例实战 -- 简易银行存取款查询系统 涉及知识点 包的调用 字典.列表的混合运用 列表元素索引.追加 基本的循环与分支结构 源码 import sys import time ban ...

  3. Opencv图像分割小案例 --- 绿幕背景视频抠图

    基于HSV色彩空间的实时背景替换: 注:新更换的背景图必须和原视频的背景图尺寸一样.  相关API: 1. inRange()函数 opencv中的inRange()函数可实现二值化功能(这点类似th ...

  4. 微信小程序实战(二)---实现搜索页面

    第一篇写了一个小程序的登录界面,昨天想要写一个仿淘宝的搜索商品页面,不管什么样的小程序,对于搜索都是会有一些需要的,所以搜索页面还是可以复用的. 因为只是写个搜索页面,所以主页面就没有好好切,见谅.. ...

  5. Jetson Nano 从入门到实战(转载)(案例:Opencv配置、人脸检测、二维码检测)

    目录 1. Jetson Nano简介 2. Jetson Nano环境配置 2.1 开箱配件介绍 2.2 烧录系统 2.3 开机和基本设置 2.4 开发环境配置 2.4.1 更新源和软件 2.4.2 ...

  6. OpenCV C++案例实战三《二维码检测》

    OpenCV C++案例实战三<二维码检测> 前言 一.二维码检测 二.二维码识别 1.通过findContours找到轮廓层级关系 三.二维码绘制 四.源码 总结 前言 本文将使用Ope ...

  7. Jetson Nano 从入门到实战(案例:Opencv配置、人脸检测、二维码检测)

    目录 1. Jetson Nano简介 2. Jetson Nano环境配置 2.1 开箱配件介绍 2.2 烧录系统 2.3 开机和基本设置 2.4 开发环境配置 2.4.1 更新源和软件 2.4.2 ...

  8. OpenCV C++案例实战二十九《遥感图像分割》

    OpenCV C++案例实战二十九<遥感图像分割> 前言 一.准备数据 二.K-Means分类 三.效果显示 四.源码 总结 前言 本案例基于k-means机器学习算法进行遥感图像分割.主 ...

  9. OpenCV C++案例实战二《生成蒙太奇图像》

    OpenCV C++案例实战二<生成蒙太奇图像> 前言 一.输入模板图像 二.读取素材图像 三.生成蒙太奇模板 四.生成蒙太奇图像 五.源码 总结 前言 本文将使用OpenCV C++ 生 ...

最新文章

  1. 控制台打印汉字的方法
  2. 卡住无法查看到所有进程_进程同步 进程互斥 软件和硬件实现方式 信号量机制 信号量机制实现进程同步,进程互斥,前驱关系...
  3. Pytorch-基于Transformer的情感分类
  4. 《LeetCode力扣练习》第160题 相交链表 Java
  5. .NET可变性解析(协变和逆变)
  6. 顺丰固定翼无人机来了,未来你的快递将一路“飞”到你手中
  7. MySql绿色版安装过程记录
  8. C++ 学习之旅(12)——static用法小结
  9. 如何使用explain进行SQL语句调优
  10. shutdown的几种方式,shutdown abort的一些弊端有哪些
  11. 需要规范日志格式_Node开发的日志规范
  12. linux----------今天又遇到一个奇葩的问题,就是linux文件的权限已经是777了但是还是没有写入权限,按照下面的命令就解决了
  13. ASP.net的PDF打印(水晶报表)[摘]
  14. @开发者 想成为行业应用开发的实力派吗?TA 或者能帮到你
  15. 【BZOJ-2768】冠军调查 最小割
  16. .net mvc 获取项目文件夹路径
  17. Linux 查找满足条件的文件并复制
  18. OpenCV-Python图像模糊处理
  19. m序列的产生原理及其性质
  20. php校花评比排名,投票|佛山“校花”颜值大比拼,快来选出你最爱的!

热门文章

  1. MySQL数据库day01
  2. 《中国美食》习字优秀作品展示
  3. JS之——解决IE6、7、8使用JSON.stringify报JSON未定义错误的问题
  4. 如何防止你的代码被窃取?Python代码加密方案汇总(带实例验证)
  5. 关于计算机网络,你需要知道的一些常识
  6. 联想宣布推出升级版数据中心产品组合——搭载全新英特尔(R)处理器和持久性内存且安全性增强
  7. 汽车诊断协议,(K线/CAN总线、kwp2000、ISO14230、ISO1575...)
  8. TMS570学习【2】pwm输出
  9. 下载VirtualBox,创建虚拟机,安装Linux系统(Ubuntu版)
  10. Java中的锁大全(底层源码分析)