Advertisement
matejnevlud

ANO - trida

Mar 2nd, 2021
642
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.13 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "objectprocessing.h"
  3.  
  4. ObjectProcessing::ObjectProcessing(){}
  5.  
  6. void ObjectProcessing::image_thresholding(cv::Mat &input, cv::Mat &output, float threshold)
  7. {
  8.     output = cv::Mat::zeros(input.size(), input.type());
  9.     for (int y = 1; y < input.rows - 1; y++) {
  10.         for (int x = 1; x < input.cols - 1; x++) {
  11.             if (input.at<float>(y, x) > threshold) {
  12.                 output.at<float>(y, x) = 1.0f;
  13.             }
  14.         }
  15.     }
  16. }
  17.  
  18. int ObjectProcessing::objects_indexing(cv::Mat & input, cv::Mat &output)
  19. {
  20.     output = cv::Mat::zeros(input.size(), input.type());
  21.     std::vector<cv::Point> points;
  22.     cv::Point lookForMatrix[]{
  23.         cv::Point(1, 1), cv::Point(1, 0), cv::Point(1, -1),
  24.         cv::Point(0, 1),                  cv::Point(0, -1),
  25.         cv::Point(-1, 1), cv::Point(-1, 0), cv::Point(-1, 1)
  26.     };
  27.     int lookForMatrixSize = sizeof(lookForMatrix) / sizeof(cv::Point); 
  28.     int o_id = 1;  
  29.     for (int y = 0; y < input.rows; y++) {
  30.         for (int x = 0; x < input.cols; x++) {
  31.             if (input.at<float>(y, x) != 0.0f) {
  32.                 bool indexed = false;
  33.                 points.push_back(cv::Point(x, y));
  34.  
  35.                 while (!points.empty()) {
  36.                     cv::Point point = points[points.size() - 1];
  37.                     points.pop_back();
  38.                     if (point.x > 0 && point.y > 0 && point.x < input.cols - 1 && point.y < input.rows - 1) {
  39.                         if (output.at<float>(point) != 0.0f) {
  40.                             continue;
  41.                         }
  42.                         for (int i = 0; i < lookForMatrixSize; i++) {
  43.                             cv::Point pointToCheck = point + lookForMatrix[i];
  44.                             if (input.at<float>(pointToCheck) != 0.0f) {
  45.                                 points.push_back(pointToCheck);
  46.                             }
  47.                         }
  48.                         indexed = true;
  49.                     }
  50.                     output.at<float>(point) = o_id;
  51.                 }
  52.                 if (indexed) {
  53.                     o_id++;
  54.                 }
  55.             }
  56.         }
  57.     }
  58.     return o_id;
  59. }
  60.  
  61. void ObjectProcessing::paint_objects(cv::Mat & source, cv::Mat & output, int objects)
  62. {
  63.     output = cv::Mat::zeros(source.size(), CV_32FC3);
  64.     std::vector<cv::Vec3f> colors;
  65.     colors.push_back(cv::Vec3f());
  66.  
  67.     for (int i = 0; i < objects; i++) {
  68.         colors.push_back(create_color());
  69.     }
  70.  
  71.     for (int y = 0; y < source.rows; y++) {
  72.         for (int x = 0; x < source.cols; x++) {
  73.             output.at<cv::Vec3f>(y, x) = colors[source.at<float>(y, x)];
  74.         }
  75.     }
  76. }
  77.  
  78. std::vector<float*> ObjectProcessing::features_extraction(cv::Mat & input, int objects, std::vector<float> &coordinate_areas, std::vector<float> &mass_areas, std::vector<float> &perimeters, std::vector<float> &F1, std::vector<float> &F2, std::vector<float> &uMin, std::vector<float> &uMax)
  79. {
  80.     std::vector<cv::Mat> coordinate_moments;
  81.     std::vector<cv::Mat> center_of_the_mass_moments;
  82.     std::vector<float*> centersOfMasses;
  83.     get_moments_for_coordinate(input, coordinate_moments, perimeters, objects);
  84.     get_moments_center_mass(input, coordinate_moments, center_of_the_mass_moments);
  85.     get_classification_moments(center_of_the_mass_moments, perimeters, F1, F2, uMin, uMax);
  86.     coordinate_areas = get_areas(coordinate_moments);
  87.     mass_areas = get_areas(center_of_the_mass_moments);
  88.     centersOfMasses = get_centers(coordinate_moments);
  89.     return centersOfMasses;
  90. }
  91.  
  92. std::vector<float*> ObjectProcessing::compute_etalons(cv::Mat &input, int objects, std::vector<float> &F1, std::vector<float> &F2, cv::Mat &output){
  93.     std::vector<float*> etalon_classes;
  94.     output = cv::Mat(input.size(), CV_32FC3, cv::Scalar(0.0, 0.0, 0.0));
  95.  
  96.     // check wrong data
  97.     for (int i = 1; i < objects; i++) {
  98.         if (isnan(F1[i]) || isnan(F2[i])) {
  99.             objects -= 1;
  100.             F1.erase(F1.begin() + i);
  101.             F2.erase(F2.begin() + i);
  102.         }
  103.     }
  104.  
  105.     float old_f1 = F1[1];
  106.     float old_f2 = F2[1];
  107.     float etalon_f1 = 0;
  108.     float etalon_f2 = 0;
  109.     int Nr = 0;
  110.     for (int i = 1; i < objects; i++) {    
  111.         cv::circle(output, cv::Point(F1[i] * output.cols, F2[i] * output.rows), 3, cv::Vec3f(1.0, 1.0, 1.0));
  112.         if (!isnan(F1[i]) && !isnan(F2[i])) {  
  113.             if (round(F1[i]) == round(old_f1) && round(F2[i]) == round(old_f2))    
  114.             {
  115.                 etalon_f1 += F1[i];
  116.                 etalon_f2 += F2[i];
  117.                 Nr += 1;
  118.             }
  119.             else {  // add etalon new class
  120.                 float *x = new float[2];
  121.                 x[0] = (1.0f / (float)Nr) * etalon_f1;
  122.                 x[1] = (1.0f / (float)Nr) * etalon_f2;
  123.                 etalon_classes.push_back(x);
  124.                 etalon_f1 = 0;
  125.                 etalon_f2 = 0;
  126.                 Nr = 0;
  127.             }
  128.             if (i == objects - 1) { // add etalon last class
  129.                 float *x = new float[2];
  130.                 x[0] = (1.0f / (float)Nr) * etalon_f1;
  131.                 x[1] = (1.0f / (float)Nr) * etalon_f2;
  132.                 etalon_classes.push_back(x);
  133.             }
  134.             old_f1 = F1[i];
  135.             old_f2 = F2[i];
  136.         }
  137.     }
  138.     for (int i = 0; i < etalon_classes.size(); i++) {
  139.         float *etalon = etalon_classes[i];
  140.         float x = etalon[0] * output.cols;
  141.         float y = etalon[1] * output.rows;
  142.         cv::Vec3f color = create_color();
  143.         cv::circle(output, cv::Point(x, y), 4, color, -1);
  144.     }
  145.  
  146.     return etalon_classes;
  147. }
  148.  
  149. void ObjectProcessing::classify_by_etalons(cv::Mat &input, cv::Mat &output, std::vector<float*> centerOfMasses, std::vector<float*> etalons, std::vector<float> &F1, std::vector<float> &F2, int objects) {
  150.     output = input.clone();
  151.     cv::cvtColor(output, output, cv::COLOR_GRAY2BGR);
  152.     std::vector<cv::Vec3f> colors;
  153.  
  154.     // check wrong data
  155.     for (int i = 1; i < objects; i++) {
  156.         if (isnan(F1[i]) || isnan(F2[i])) {
  157.             objects -= 1;
  158.             centerOfMasses.erase(centerOfMasses.begin() + i);
  159.             F1.erase(F1.begin() + i);
  160.             F2.erase(F2.begin() + i);
  161.         }
  162.     }
  163.  
  164.     for (int j = 0; j < etalons.size(); j++) {
  165.         colors.push_back(create_color());
  166.     }
  167.  
  168.     for (int i = 1; i < objects; i++) {
  169.         float distance = 100.0f;
  170.         float etalon_index;
  171.         for (int j = 0; j < etalons.size(); j++) {
  172.             float * etalon = etalons[j];
  173.             float x = etalon[0] - F1[i];
  174.             float y = etalon[1] - F2[i];
  175.             float dist;
  176.             dist = pow(x, 2) + pow(y, 2);    
  177.             dist = sqrt(dist);
  178.  
  179.             if (dist < distance)
  180.             {
  181.                 distance = dist;
  182.                 etalon_index = j;
  183.             }
  184.         }
  185.  
  186.         float *center = centerOfMasses[i];
  187.         cv::Vec3f color = colors[etalon_index];
  188.         cv::circle(output, cv::Point(center[0], center[1]), 7, color, -1);
  189.     }
  190.  
  191. }
  192.  
  193. std::vector<float*> ObjectProcessing::compute_kmeans(cv::Mat &input, int objects, std::vector<float> &F1, std::vector<float> &F2, cv::Mat &output, int numOfClusters, int &stepsOverall) {
  194.     std::vector<cv::Vec3f> colors;
  195.     output = cv::Mat(input.size(), CV_32FC3, cv::Scalar(0.0, 0.0, 0.0));
  196.     std::random_device rd;
  197.     std::mt19937 eng(rd());
  198.     std::uniform_int_distribution<> distrx(0, 1);
  199.     std::uniform_int_distribution<> distry(0, 1);
  200.  
  201.     std::vector<float*> centroids;
  202.     std::vector<float*> points;
  203.     bool find_new_centroids = true;
  204.  
  205.     // check wrong data
  206.     for (int i = 1; i < objects; i++) {
  207.         if (isnan(F1[i]) || isnan(F2[i])) {
  208.             objects -= 1;
  209.             F1.erase(F1.begin() + i);
  210.             F2.erase(F2.begin() + i);
  211.         }
  212.     }
  213.  
  214.     for (int i = 0; i < numOfClusters; i++) {
  215.         float *cent = new float[2];
  216.         cent[0] = distrx(eng);
  217.         cent[1] = distry(eng);
  218.         centroids.push_back(cent);
  219.         colors.push_back(create_color());
  220.     }
  221.  
  222.     for (int i = 1; i < objects; i++) {
  223.         float* point = new float[2];
  224.         point[0] = F1[i];
  225.         point[1] = F2[i];
  226.         points.push_back(point);
  227.         cv::circle(output, cv::Point(F1[i] * output.cols,F2[i] * output.rows), 3, cv::Vec3f(1.0, 1.0, 1.0));
  228.     }
  229.    
  230.     // main loop
  231.     std::vector<int> old_assignment;
  232.     while (find_new_centroids) {
  233.         std::vector<int> points_assignment_idx;
  234.         // distance for each point
  235.         for (int i = 0; i < points.size(); i++) {
  236.             int close_idx = 0;
  237.             float distance = 10000.0f;
  238.             float* point = new float[2];
  239.             point = points[i];
  240.  
  241.             for (int j = 0; j < centroids.size(); j++) {
  242.                 float dist;
  243.                 float *cent = centroids[j];
  244.                 dist = pow(cent[0] - point[0], 2) + pow(cent[1] - point[1], 2);
  245.                 dist = sqrt(dist);  // new distance
  246.                 if (dist < distance)
  247.                 {
  248.                     distance = dist;
  249.                     close_idx = j;
  250.                 }
  251.             }
  252.             points_assignment_idx.push_back(close_idx);
  253.         }
  254.  
  255.         // calculate new centroids
  256.         for (int i = 0; i < centroids.size(); i++) {
  257.             int numOfPoints = 0;
  258.             float meanx = 0;
  259.             float meany = 0;
  260.             for (int j = 0; j < points.size(); j++) {
  261.                 if (points_assignment_idx[j] == i) {    // if is assigned to centroid
  262.                     numOfPoints += 1;
  263.                     float *point = new float[2];
  264.                     point = points[j];
  265.                     meanx += point[0];
  266.                     meany += point[1];
  267.                 }
  268.             }
  269.             if (numOfPoints > 0) {
  270.                 float* cent = new float[2];
  271.                 cent[0] = meanx / numOfPoints;
  272.                 cent[1] = meany / numOfPoints;
  273.                 centroids[i] = cent;
  274.             }
  275.         }
  276.        
  277.         if (old_assignment == points_assignment_idx)
  278.             find_new_centroids = false;
  279.         else
  280.             old_assignment.swap(points_assignment_idx);
  281.         stepsOverall++;
  282.     }
  283.     // end of loop - final centroids
  284.  
  285.     for (int i = 0; i < centroids.size(); i++) {
  286.         float * cent = centroids[i];
  287.         cv::circle(output, cv::Point(cent[0] * output.cols, cent[1] * output.rows), 4, colors[i], -1);
  288.     }
  289.     return centroids;
  290. }
  291.  
  292. void ObjectProcessing::classify_by_kmeans(cv::Mat &input, cv::Mat &output, std::vector<float*> centerOfMasses, std::vector<float*> kmeans, std::vector<float> &F1, std::vector<float> &F2, int objects) {
  293.     output = input.clone();
  294.     cv::cvtColor(output, output, cv::COLOR_GRAY2BGR);
  295.     std::vector<cv::Vec3f> colors;
  296.  
  297.     // check wrong data
  298.     for (int i = 1; i < objects; i++) {
  299.         if (isnan(F1[i]) || isnan(F2[i])) {
  300.             objects -= 1;
  301.             centerOfMasses.erase(centerOfMasses.begin() + i);
  302.             F1.erase(F1.begin() + i);
  303.             F2.erase(F2.begin() + i);
  304.         }
  305.     }
  306.  
  307.     for (int j = 0; j < kmeans.size(); j++) {
  308.         colors.push_back(create_color());
  309.     }
  310.  
  311.     for (int i = 1; i < objects; i++) {
  312.         float distance = 10000.0f;
  313.         float centroid_index = 0;
  314.         for (int j = 0; j < kmeans.size(); j++) {
  315.             float * kmean = kmeans[j];
  316.             float x = kmean[0] - F1[i];
  317.             float y = kmean[1] - F2[i];
  318.             float dist;
  319.             dist = pow(x, 2) + pow(y, 2);
  320.             dist = sqrt(dist);
  321.  
  322.             if (dist < distance)
  323.             {
  324.                 distance = dist;
  325.                 centroid_index = j;
  326.             }
  327.         }
  328.  
  329.         float *center = centerOfMasses[i];
  330.         cv::Vec3f color = colors[centroid_index];
  331.         cv::circle(output, cv::Point(center[0], center[1]), 7, color, -1);
  332.     }
  333.  
  334. }
  335.  
  336. void ObjectProcessing::put_index_numbers_in_image(cv::Mat &source, std::vector<float*> centerOfMasses, std::vector<float> &F1, std::vector<float> &F2, int objects) {
  337.     float f1 = F1[1];
  338.     float f2 = F2[1];
  339.     int oid = 1;
  340.     for (int i = 1; i < objects; i++) {
  341.         float *cn = centerOfMasses[i];
  342.         if (round(F1[i]) == round(f1) && round(F2[i]) == round(f2))
  343.             cv::putText(source, IntToString(oid), cv::Point(cn[0], cn[1]), cv::FONT_HERSHEY_SIMPLEX, 0.3, cv::Scalar(0.0, 0.0, 0.0));
  344.         else {
  345.             oid++;
  346.             cv::putText(source, IntToString(oid), cv::Point(cn[0], cn[1]), cv::FONT_HERSHEY_SIMPLEX, 0.3, cv::Scalar(0.0, 0.0, 0.0));
  347.         }
  348.         f1 = F1[i];
  349.         f2 = F2[i];
  350.     }
  351. }
  352.  
  353. void ObjectProcessing::get_moments_for_coordinate(cv::Mat & input, std::vector<cv::Mat>& moments, std::vector<float>& perimeters, int objects)
  354. {
  355.     for (int i = 0; i < objects; i++) {
  356.         moments.push_back(cv::Mat::zeros(cv::Size(2, 2), input.type()));
  357.         perimeters.push_back(0.0f);
  358.     }
  359.     cv::Point lookForMatrix[]{
  360.         cv::Point(1, 0),
  361.         cv::Point(0, 1),               
  362.         cv::Point(0, -1),
  363.         cv::Point(-1, 0)
  364.     };
  365.     int lookForMatrixSize = sizeof(lookForMatrix) / sizeof(cv::Point); 
  366.  
  367.     for (int y = 0; y < input.rows; y++) {
  368.         for (int x = 0; x < input.cols; x++) {
  369.             int o_id = 0;
  370.             if ((o_id = input.at<float>(y, x)) != 0.0f) {
  371.                 cv::Mat objectMoment = moments[o_id];
  372.                 for (int q = 0; q < objectMoment.rows; q++) {
  373.                     for (int p = 0; p < objectMoment.cols; p++) {
  374.                         objectMoment.at<float>(q, p) += pow(x, p) * pow(y, q);
  375.                     }
  376.                 }
  377.                 moments[o_id] = objectMoment;
  378.                 cv::Point point = cv::Point(x, y);
  379.  
  380.                 if (point.x > 0 && point.y > 0 && point.x < input.cols - 1 && point.y < input.rows - 1) {
  381.                     int perimeterCounter = 0;
  382.                     for (int i = 0; i < lookForMatrixSize; i++) {
  383.                         cv::Point pointToCheck = point + lookForMatrix[i];
  384.                         if (input.at<float>(pointToCheck) == o_id) {
  385.                             perimeterCounter++;
  386.                         }
  387.                     }
  388.                     if (perimeterCounter != lookForMatrixSize) {
  389.                         perimeters[o_id]++;
  390.                     }
  391.                 }
  392.             }
  393.         }
  394.     }
  395. }
  396.  
  397. void ObjectProcessing::get_moments_center_mass(cv::Mat & input, std::vector<cv::Mat>& coordMoments, std::vector<cv::Mat>& massMoments)
  398. {
  399.     for (int i = 0; i < coordMoments.size(); i++) {
  400.         massMoments.push_back(cv::Mat::zeros(cv::Size(3, 3), input.type()));
  401.     }
  402.     for (int y = 0; y < input.rows; y++) {
  403.         for (int x = 0; x < input.cols; x++) {
  404.             int o_id = 0;
  405.             if ((o_id = input.at<float>(y, x)) != 0.0f) {
  406.                 cv::Mat objectMoment = massMoments[o_id];
  407.                 for (int q = 0; q < objectMoment.rows; q++) {
  408.                     for (int p = 0; p < objectMoment.cols; p++) {
  409.                         float* centerOfMass = get_center(coordMoments[o_id]);
  410.                         objectMoment.at<float>(q, p) += pow(x - centerOfMass[0], p) * pow(y - centerOfMass[1], q);
  411.                         delete centerOfMass;
  412.                     }
  413.                 }
  414.                 massMoments[o_id] = objectMoment;  
  415.             }
  416.         }
  417.     }
  418. }
  419.  
  420. void ObjectProcessing::get_classification_moments(std::vector<cv::Mat>& inputMoments, std::vector<float>& inputPerimeters, std::vector<float>& F1, std::vector<float>& F2, std::vector<float>& uMin, std::vector<float>& uMax)
  421. {
  422.     for (int i = 0; i < inputMoments.size(); i++) {
  423.         F1.push_back(get_F1(inputPerimeters[i], get_area(inputMoments[i])));
  424.         uMin.push_back(get_uMin(inputMoments[i]));
  425.         uMax.push_back(get_uMax(inputMoments[i]));
  426.         F2.push_back(get_F2(uMin[i], uMax[i]));
  427.     }
  428. }
  429.  
  430. float ObjectProcessing::get_F1(float perimeter, float area)
  431. {
  432.     return pow(perimeter, 2) / (100.0f * area);
  433. }
  434.  
  435. float ObjectProcessing::get_F2(float uMin, float uMax)
  436. {
  437.     return uMin / uMax;
  438. }
  439.  
  440. float ObjectProcessing::get_uMin(cv::Mat centerOfTheMassMoment)
  441. {
  442.     return 0.5f * (centerOfTheMassMoment.at<float>(0, 2) + centerOfTheMassMoment.at<float>(2, 0)) - 0.5f * sqrt(4 * pow(centerOfTheMassMoment.at<float>(1, 1), 2) + pow(centerOfTheMassMoment.at<float>(0, 2) - centerOfTheMassMoment.at<float>(2, 0), 2));
  443. }
  444.  
  445. float ObjectProcessing::get_uMax(cv::Mat centerOfTheMassMoment)
  446. {
  447.     return 0.5f * (centerOfTheMassMoment.at<float>(0, 2) + centerOfTheMassMoment.at<float>(2, 0)) + 0.5f * sqrt(4 * pow(centerOfTheMassMoment.at<float>(1, 1), 2) + pow(centerOfTheMassMoment.at<float>(0, 2) - centerOfTheMassMoment.at<float>(2, 0), 2));
  448. }
  449.  
  450. std::vector<float> ObjectProcessing::get_areas(std::vector<cv::Mat>& inputMoments)
  451. {
  452.     std::vector<float> areas;
  453.     for (int i = 0; i < inputMoments.size(); i++) {
  454.         areas.push_back(get_area(inputMoments[i]));
  455.     }
  456.     return areas;
  457. }
  458.  
  459. std::vector<float*> ObjectProcessing::get_centers(std::vector<cv::Mat>& coordinateMoments)
  460. {
  461.     std::vector<float*> centersOfMasses;
  462.     for (int i = 0; i < coordinateMoments.size(); i++) {
  463.         centersOfMasses.push_back(get_center(coordinateMoments[i]));
  464.     }
  465.     return centersOfMasses;
  466. }
  467.  
  468. float ObjectProcessing::get_area(cv::Mat objectMoment)
  469. {
  470.     return objectMoment.at<float>(0, 0);
  471. }
  472.  
  473. float *ObjectProcessing::get_center(cv::Mat coordinateMoment)
  474. {
  475.     float* center = new float[2];
  476.     center[0] = coordinateMoment.at<float>(0, 1) / coordinateMoment.at<float>(0, 0);
  477.     center[1] = coordinateMoment.at<float>(1, 0) / coordinateMoment.at<float>(0, 0);
  478.     return center;
  479. }
  480.  
  481. cv::Vec3f ObjectProcessing::create_color()
  482. {
  483.     std::random_device rd;
  484.     std::mt19937 eng(rd());
  485.     std::uniform_int_distribution<> distr(50, 255);
  486.     return cv::Vec3f(float(distr(eng)) / 255, float(distr(eng)) / 255, float(distr(eng)) / 255);
  487. }
  488.  
  489. std::string ObjectProcessing::IntToString(int Number)
  490. {
  491.     std::ostringstream ss;
  492.     ss << Number;
  493.     return ss.str();
  494. }
  495.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement