#include <opencv2/opencv.hpp>
#include<vector>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
Mat src_img, gray_img, dst_img;
int threshold_value = 100; // 定义阈值,全局变量
int max_level = 255; // 定义最大阈值,全局变量
const string output_win = "Contours Result";
const string roi_win = "Final Result";
void FindROI(int, void*); //声明函数,用于找到兴趣区域
void Check_Skew(); //声明函数,用于纠正倾斜
int main()
{
/*src_img = imread("1.png");
if (src_img.empty())
{
printf("could not load the image...\n");
return -1;
}
//cv::resize(src_img, src_img, cv::Size(450, 580), (0, 0), (0, 0), cv::INTER_LINEAR);
namedWindow("原图", CV_WINDOW_AUTOSIZE);
imshow("原图", src_img);
Check_Skew(); //纠正倾斜*/
src_img = imread("12.png");
if (src_img.empty())
{
printf("could not load the image...\n");
return -1;
}
namedWindow(output_win, CV_WINDOW_AUTOSIZE);
// 接下来提取兴趣区域
createTrackbar("Threshold:", output_win, &threshold_value, max_level, FindROI);
FindROI(0, 0);
waitKey(0);
return 0;
}
void Check_Skew()
{
Mat canny_output;
cvtColor(src_img, gray_img, COLOR_BGR2GRAY); //将原图转化为灰度图
Canny(gray_img, canny_output, threshold_value, threshold_value * 2, 3, false); // canny边缘检测
imshow("canny", canny_output);
vector<vector<Point>> contours;
vector<Vec4i> hireachy;
findContours(canny_output, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); // 找到所有轮廓
Mat drawImg = Mat::zeros(src_img.size(), CV_8UC3);
float max_width = 0; // 定义最大宽度
float max_height = 0; // 定义最大高度
double degree = 0; // 定义旋转角度
for (auto t = 0; t < contours.size(); ++t) // 遍历每一个轮廓
{
RotatedRect minRect = minAreaRect(contours[t]); // 找到每一个轮廓的最小外包旋转矩形,RotatedRect里面包含了中心座标、尺寸以及旋转角度等信息
degree = abs(minRect.angle);//返回绝对值
if (degree > 0)
{
max_width = max(max_width, minRect.size.width);
max_height = max(max_height, minRect.size.height);
}
}
RNG rng(12345);
for (auto t = 0; t < contours.size(); ++t)
{
RotatedRect minRect = minAreaRect(contours[t]);
if (max_width == minRect.size.width && max_height == minRect.size.height)
{
degree = minRect.angle; // 保存目标轮廓的角度
Point2f pts[4];
minRect.points(pts);
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); //产生随机颜色
for (int i = 0; i < 4; ++i)
{
line(drawImg, pts[i], pts[(i + 1) % 4], color, 2, 8, 0);
}
}
}
imshow("找到的矩形轮廓", drawImg);
Point2f center(src_img.cols / 2, src_img.rows / 2);
Mat rotm = getRotationMatrix2D(center, degree, 1.0); //获取仿射变换矩阵
Mat dst;
warpAffine(src_img, dst, rotm, src_img.size(), INTER_LINEAR, 0, Scalar(255, 255, 255)); // 进行图像旋转操作
imwrite("12.png", dst); //将校正后的图像保存下来
imshow("Correct Image", dst);
}
void FindROI(int, void*)
{
printf("**************当前阈值:%d******************************\n", threshold_value);
cvtColor(src_img, gray_img, COLOR_BGR2GRAY); //将原图转化为灰度图
Mat canny_output;
Canny(gray_img, canny_output, threshold_value, threshold_value * 2, 3, false); // canny边缘检测
//imshow("canny_output", canny_output);
vector<vector<Point>> contours;
vector<Vec4i> hireachy;
findContours(canny_output, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); // 调用API,找到轮廓
// 筛选contours中的轮廓,我们需要最大的那个轮廓
int min_width = src_img.cols*0.5; // 矩形的最小宽度
int min_height = src_img.rows*0.5; // 矩形的最小高度
RNG rng(12345); //定义一个随机数产生器,用来产生不同颜色的矩形框
Mat drawImage = Mat::zeros(src_img.size(), CV_8UC3);
Rect bbox;
for (auto t = 0; t < contours.size(); ++t) // 遍历每一个轮廓
{
RotatedRect minRect = minAreaRect(contours[t]); // 找到每一个轮廓的最小外包旋转矩形,RotatedRect里面包含了中心座标、尺寸以及旋转角度等信息
float degree = abs(minRect.angle); // 最小外包旋转矩形的旋转角度
if (minRect.size.width > min_width && minRect.size.height > min_height && minRect.size.width < (src_img.cols - 5)) //筛选最小外包旋转矩形
{
Mat vertices; // 定义一个4行2列的单通道float类型的Mat,用来存储旋转矩形的四个顶点
boxPoints(minRect, vertices); // 计算旋转矩形的四个顶点座标
bbox = boundingRect(vertices); //找到输入点集的最小外包直立矩形,返回Rect类型
//cout << "最小外包矩形:" << bbox << endl;
//cout << "矩形四个顶点座标:" << endl<<vertices << endl;
Point2f pts[4];
minRect.points(pts);
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); //产生随机颜色
for (int i = 0; i < 4; ++i)
{
//cout << "pts" << i << "=" << pts[i] << endl;
line(drawImage, pts[i], pts[(i + 1) % 4], color, 2, 8, 0);
}
}
}
imshow(output_win, drawImage);
if (bbox.width > 0 && bbox.height > 0)
{
Mat roiImg = src_img(bbox); //从原图中截取兴趣区域
namedWindow(roi_win, CV_WINDOW_AUTOSIZE);
imshow(roi_win, roiImg);
}
return;
}