#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;
}