Georgiy031

Untitled

May 6th, 2021
776
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <vector>
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <string>
  6.  
  7. #include <opencv2/opencv.hpp>
  8.  
  9. using namespace cv;
  10. using namespace std;
  11.  
  12.  
  13. Scalar getMSSIM(const Mat& i1, const Mat& i2)
  14. {
  15.     const double C1 = 6.5025, C2 = 58.5225;
  16.     int d = CV_32F;
  17.  
  18.     Mat I1, I2;
  19.     i1.convertTo(I1, d);
  20.     i2.convertTo(I2, d);
  21.  
  22.     Mat I2_2 = I2.mul(I2);
  23.     Mat I1_2 = I1.mul(I1);
  24.     Mat I1_I2 = I1.mul(I2);
  25.  
  26.  
  27.     Mat mu1, mu2;
  28.     GaussianBlur(I1, mu1, Size(11, 11), 1.5);
  29.     GaussianBlur(I2, mu2, Size(11, 11), 1.5);
  30.  
  31.     Mat mu1_2 = mu1.mul(mu1);
  32.     Mat mu2_2 = mu2.mul(mu2);
  33.     Mat mu1_mu2 = mu1.mul(mu2);
  34.  
  35.     Mat sigma1_2, sigma2_2, sigma12;
  36.  
  37.     GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
  38.     sigma1_2 -= mu1_2;
  39.  
  40.     GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
  41.     sigma2_2 -= mu2_2;
  42.  
  43.     GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
  44.     sigma12 -= mu1_mu2;
  45.  
  46.     Mat t1, t2, t3;
  47.  
  48.     t1 = 2 * mu1_mu2 + C1;
  49.     t2 = 2 * sigma12 + C2;
  50.     t3 = t1.mul(t2);
  51.  
  52.     t1 = mu1_2 + mu2_2 + C1;
  53.     t2 = sigma1_2 + sigma2_2 + C2;
  54.     t1 = t1.mul(t2);
  55.  
  56.     Mat ssim_map;
  57.     divide(t3, t1, ssim_map);
  58.  
  59.     Scalar mssim = mean(ssim_map);
  60.     return mssim;
  61. }
  62.  
  63.  
  64. double calcMatch(const Mat& lhs, const Mat& rhs) {
  65.     int count = 0;
  66.     for (int i = 0; i < lhs.rows; ++i) {
  67.         for (int j = 0; j < lhs.cols; ++j) {
  68.             if (lhs.at<uchar>(i, j) != rhs.at<uchar>(i, j)) {
  69.                 ++count;
  70.             }
  71.         }
  72.     }
  73.     return 1.0 - count * 1.0 / (lhs.size().area());
  74. }
  75.  
  76. const size_t img_width = 2100;
  77. const size_t img_height = 2970;
  78.  
  79.  
  80. int main() {
  81.     vector<string> files = { "P_20210309_064128_vHDR_Auto.jpg",
  82.                              "P_20210410_170858_vHDR_On.jpg" ,
  83.                              "P_20210410_170941_vHDR_On.jpg" ,
  84.                              "P_20210410_171129_vHDR_On.jpg" ,
  85.                              "P_20210410_171136_vHDR_On.jpg" ,
  86.                              "P_20210410_171334_vHDR_On.jpg"
  87.     };
  88.  
  89.     int k = files.size();
  90.    
  91.     //считывание изображений
  92.     vector<Mat> src(k);
  93.     for (int i = 0; i < k; ++i) {
  94.         src[i] = imread(files[i]);
  95.     }
  96.    
  97.     //подготовка изображений
  98.     vector<Mat> prepared(k);
  99.     for (int i = 0; i < k; ++i) {
  100.         Mat gr, bl, di, bin;
  101.         cvtColor(src[i], gr, COLOR_BGR2GRAY);
  102.         GaussianBlur(gr, bl, { 3, 3 }, 0);
  103.         dilate(bl, di, getStructuringElement(cv::MORPH_RECT, cv::Point(9, 9)));
  104.         adaptiveThreshold(di, bin, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 51, 5);
  105.         medianBlur(bin, prepared[i], 3);
  106.     }
  107.  
  108.     //выделение границ и линий
  109.     for (int i = 0; i < k; ++i) {
  110.         Mat edges;
  111.         Canny(prepared[i], edges, 0, 300);
  112.  
  113.         vector<Vec4i> lines;
  114.         HoughLinesP(edges, lines, 1, CV_PI / 180, 1, 1, 20);
  115.         for (auto& l : lines) {
  116.             line(edges, Point(l[0], l[1]), Point(l[2], l[3]), cv::Scalar(255, 0, 0), 3, 8);
  117.         }
  118.         edges.copyTo(prepared[i]);
  119.     }
  120.  
  121.     //определение контуров документа
  122.     vector<Mat> result(k);
  123.     vector<vector<Point>> points(k);
  124.  
  125.     for (int i = 0; i < k; ++i) {
  126.         medianBlur(prepared[i], prepared[i], 9);
  127.         bitwise_not(prepared[i], prepared[i]);
  128.  
  129.         vector<vector<Point>> contours;
  130.         vector<Vec4i> hierarchy;
  131.  
  132.         findContours(prepared[i], contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE);
  133.         sort(contours.begin(), contours.end(), [](vector<Point>& lhs, vector<Point>& rhs) {
  134.             return fabs(contourArea(Mat(lhs))) < fabs(contourArea(Mat(rhs)));
  135.         });
  136.         vector<Point> mainContour = contours.back();
  137.         double perimetr = arcLength(mainContour, true);
  138.  
  139.         Mat approx;
  140.         approxPolyDP(mainContour, approx, 0.02 * perimetr, true);
  141.  
  142.         src[i].copyTo(result[i]);
  143.         points[i] = approx;
  144.         Point pt = points[i].back();
  145.         for (int j = 0; j < points[i].size(); ++j) {
  146.             line(result[i], pt, points[i][j], { 108, 73, 255 }, 8, LINE_8);
  147.             pt = points[i][j];
  148.         }
  149.         imwrite("result" + to_string(i) + ".jpg", result[i]);
  150.     }
  151.  
  152.     //совмещение документов
  153.     vector<Point> frame = { {0, 0}, {0, img_height}, {img_width, img_height}, {img_width, 0} };
  154.     vector<Mat> projections(k);
  155.  
  156.     for (int i = 0; i < k; ++i) {
  157.         Mat perspective = findHomography(points[i], frame, RANSAC);
  158.         warpPerspective(src[i], projections[i], perspective, Size{ img_width,img_height });
  159.         imwrite("projection" + to_string(i) + ".jpg", projections[i]);
  160.     }
  161.  
  162.     //бинаризация документов
  163.     vector<Mat> binarization(k);
  164.     for (int i = 0; i < k; ++i) {
  165.         Mat temp;
  166.         cvtColor(projections[i], temp, COLOR_BGR2GRAY);
  167.         adaptiveThreshold(temp, binarization[i], 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 111, 15);
  168.         imwrite("binarization" + to_string(i) + ".jpg", binarization[i]);
  169.     }
  170.  
  171.     //оценка качества
  172.     Mat etalon_input = imread("etalon.jpg"), gray, etalon;
  173.     cvtColor(etalon_input, gray, COLOR_BGR2GRAY);
  174.     adaptiveThreshold(gray, etalon, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 111, 15);
  175.    
  176.     vector<Mat> difference(k);
  177.     for (int i = 0; i < k; ++i) {
  178.         bitwise_xor(etalon, binarization[i], difference[i]);
  179.         imwrite("difference" + to_string(i) + ".jpg", difference[i]);
  180.  
  181.         cout << files[i] << ":" << endl;
  182.         cout << "Match with etalon = " << calcMatch(etalon, binarization[i]) << endl;
  183.         cout << "Structure similarity = " << getMSSIM(etalon, binarization[i])[0] << endl;
  184.         cout << endl;
  185.     }
  186.     waitKey(0);
  187. }
  188.  
  189. /*
  190. *
  191. ### Задание
  192. 1. Реализовать выделение "границ и уголков" на фотографиях документа.
  193. 2. Реализовать детектирование наиболее правдоподобного четырехугольника изображения страницы документа на фото.
  194. 3. Используя эталонную геометрическую разметку из лабораторной 5 реализовать численную оценку качества выделения отдельных примитивов и финального результата для отдельных изображений и для набора.
  195. 4. Реализовать представление результатов выполнения лабораторной (иллюстрации, таблицы, графики и т.д.) и вставить в отчет.
  196. */
RAW Paste Data