OPENCV實例:文件掃描切邊程序

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章