问题描述
真实案例,扫描仪扫描到的法律文件,需要切边,去掉边 缘空白,这样看上去才真实。
#include#include #include using namespace cv; using namespace std; #define IMAGE_PATH "D:/case2.png" Mat src, gray_src, tmp_src, dst; int threshold_value = 100; int max_level = 255; const char* roi_win = "Final Result"; void FindROI(int, void*); void Check_Skew(int, void*); int main(int argc, char** argv) { src = imread(IMAGE_PATH); if (src.empty()) { printf("could not load image...\n"); return -1; } namedWindow("input image", CV_WINDOW_AUTOSIZE); imshow("input image", src); //纠正图像角度 Check_Skew(0, 0); //图像切边 FindROI(0, 0); waitKey(0); return 0; } void Check_Skew(int, void*) { //寻找最大轮廓 Mat canny_output; cvtColor(src, gray_src, COLOR_BGR2GRAY); //Canny 算法做边缘检测 Canny(gray_src, canny_output, threshold_value, threshold_value * 2, 3, false); //在二值图像中寻找轮廓 vector > contours; vector hireachy; findContours(canny_output, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); //创建一张黑色的图,每个像素的每个通道都为0,Scalar(0,0,0) //Mat drawImg = Mat::zeros(src.size(), CV_8UC3); float maxw = 0;//矩形宽 float maxh = 0;//矩形高 double degree = 0; for (size_t t = 0; t < contours.size(); t++) { RotatedRect minRect = minAreaRect(contours[t]); //矩形角度绝对值 degree = abs(minRect.angle); if (degree > 0) { maxw = max(maxw, minRect.size.width); maxh = max(maxh, minRect.size.height); } if (degree > 0) { if (maxw == minRect.size.width && maxh == minRect.size.height) { degree = minRect.angle; } } } printf("max contours width : %f\n", maxw); printf("max contours height : %f\n", maxh); printf("max contours angle : %f\n\n\n", degree); //寻找几何中心 Point2f center(src.cols / 2, src.rows / 2); //旋转degree角度 Mat rotm = getRotationMatrix2D(center, degree, 1.0); //对图像做仿射变换 warpAffine(src, tmp_src, rotm, src.size(), INTER_LINEAR, 0, Scalar(255, 255, 255)); imshow("Correct Image", tmp_src); } void FindROI(int, void*) { //灰度图 cvtColor(tmp_src, gray_src, COLOR_BGR2GRAY); Mat canny_output; //Canny 算法做边缘检测 Canny(gray_src, canny_output, threshold_value, threshold_value * 2, 3, false); //在二值图像中寻找轮廓 vector > contours; vector hireachy; findContours(canny_output, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); //定义最小轮廓 float minw = tmp_src.cols*0.5; float minh = tmp_src.rows*0.5; float minstW = 0.0; bool bfirst = true; RotatedRect minstRect; Rect bbox; for (size_t t = 0; t < contours.size(); t++) { RotatedRect minRect = minAreaRect(contours[t]); if (minRect.size.width > minw && minRect.size.height > minh && minRect.size.width < (src.cols - 20)) { { //找宽度最小的矩形,既是要找的图像。 printf("t = %d, w = %f , h = %f \n",t, minRect.size.width, minRect.size.height); if (bfirst) { minstW = minRect.size.width; minstRect = minRect; bfirst = false; } else { float tmp = min(minstW, minRect.size.width); if (tmp < minstW) { minstW = tmp; minstRect = minRect; } } } } } bbox = minstRect.boundingRect(); if (bbox.width > 0 && bbox.height > 0) { Mat roiImg = tmp_src(bbox); imshow(roi_win, roiImg); } return; }