Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- #include "objectprocessing.h"
- ObjectProcessing::ObjectProcessing(){}
- void ObjectProcessing::image_thresholding(cv::Mat &input, cv::Mat &output, float threshold)
- {
- output = cv::Mat::zeros(input.size(), input.type());
- for (int y = 1; y < input.rows - 1; y++) {
- for (int x = 1; x < input.cols - 1; x++) {
- if (input.at<float>(y, x) > threshold) {
- output.at<float>(y, x) = 1.0f;
- }
- }
- }
- }
- int ObjectProcessing::objects_indexing(cv::Mat & input, cv::Mat &output)
- {
- output = cv::Mat::zeros(input.size(), input.type());
- std::vector<cv::Point> points;
- cv::Point lookForMatrix[]{
- cv::Point(1, 1), cv::Point(1, 0), cv::Point(1, -1),
- cv::Point(0, 1), cv::Point(0, -1),
- cv::Point(-1, 1), cv::Point(-1, 0), cv::Point(-1, 1)
- };
- int lookForMatrixSize = sizeof(lookForMatrix) / sizeof(cv::Point);
- int o_id = 1;
- for (int y = 0; y < input.rows; y++) {
- for (int x = 0; x < input.cols; x++) {
- if (input.at<float>(y, x) != 0.0f) {
- bool indexed = false;
- points.push_back(cv::Point(x, y));
- while (!points.empty()) {
- cv::Point point = points[points.size() - 1];
- points.pop_back();
- if (point.x > 0 && point.y > 0 && point.x < input.cols - 1 && point.y < input.rows - 1) {
- if (output.at<float>(point) != 0.0f) {
- continue;
- }
- for (int i = 0; i < lookForMatrixSize; i++) {
- cv::Point pointToCheck = point + lookForMatrix[i];
- if (input.at<float>(pointToCheck) != 0.0f) {
- points.push_back(pointToCheck);
- }
- }
- indexed = true;
- }
- output.at<float>(point) = o_id;
- }
- if (indexed) {
- o_id++;
- }
- }
- }
- }
- return o_id;
- }
- void ObjectProcessing::paint_objects(cv::Mat & source, cv::Mat & output, int objects)
- {
- output = cv::Mat::zeros(source.size(), CV_32FC3);
- std::vector<cv::Vec3f> colors;
- colors.push_back(cv::Vec3f());
- for (int i = 0; i < objects; i++) {
- colors.push_back(create_color());
- }
- for (int y = 0; y < source.rows; y++) {
- for (int x = 0; x < source.cols; x++) {
- output.at<cv::Vec3f>(y, x) = colors[source.at<float>(y, x)];
- }
- }
- }
- 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)
- {
- std::vector<cv::Mat> coordinate_moments;
- std::vector<cv::Mat> center_of_the_mass_moments;
- std::vector<float*> centersOfMasses;
- get_moments_for_coordinate(input, coordinate_moments, perimeters, objects);
- get_moments_center_mass(input, coordinate_moments, center_of_the_mass_moments);
- get_classification_moments(center_of_the_mass_moments, perimeters, F1, F2, uMin, uMax);
- coordinate_areas = get_areas(coordinate_moments);
- mass_areas = get_areas(center_of_the_mass_moments);
- centersOfMasses = get_centers(coordinate_moments);
- return centersOfMasses;
- }
- std::vector<float*> ObjectProcessing::compute_etalons(cv::Mat &input, int objects, std::vector<float> &F1, std::vector<float> &F2, cv::Mat &output){
- std::vector<float*> etalon_classes;
- output = cv::Mat(input.size(), CV_32FC3, cv::Scalar(0.0, 0.0, 0.0));
- // check wrong data
- for (int i = 1; i < objects; i++) {
- if (isnan(F1[i]) || isnan(F2[i])) {
- objects -= 1;
- F1.erase(F1.begin() + i);
- F2.erase(F2.begin() + i);
- }
- }
- float old_f1 = F1[1];
- float old_f2 = F2[1];
- float etalon_f1 = 0;
- float etalon_f2 = 0;
- int Nr = 0;
- for (int i = 1; i < objects; i++) {
- cv::circle(output, cv::Point(F1[i] * output.cols, F2[i] * output.rows), 3, cv::Vec3f(1.0, 1.0, 1.0));
- if (!isnan(F1[i]) && !isnan(F2[i])) {
- if (round(F1[i]) == round(old_f1) && round(F2[i]) == round(old_f2))
- {
- etalon_f1 += F1[i];
- etalon_f2 += F2[i];
- Nr += 1;
- }
- else { // add etalon new class
- float *x = new float[2];
- x[0] = (1.0f / (float)Nr) * etalon_f1;
- x[1] = (1.0f / (float)Nr) * etalon_f2;
- etalon_classes.push_back(x);
- etalon_f1 = 0;
- etalon_f2 = 0;
- Nr = 0;
- }
- if (i == objects - 1) { // add etalon last class
- float *x = new float[2];
- x[0] = (1.0f / (float)Nr) * etalon_f1;
- x[1] = (1.0f / (float)Nr) * etalon_f2;
- etalon_classes.push_back(x);
- }
- old_f1 = F1[i];
- old_f2 = F2[i];
- }
- }
- for (int i = 0; i < etalon_classes.size(); i++) {
- float *etalon = etalon_classes[i];
- float x = etalon[0] * output.cols;
- float y = etalon[1] * output.rows;
- cv::Vec3f color = create_color();
- cv::circle(output, cv::Point(x, y), 4, color, -1);
- }
- return etalon_classes;
- }
- 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) {
- output = input.clone();
- cv::cvtColor(output, output, cv::COLOR_GRAY2BGR);
- std::vector<cv::Vec3f> colors;
- // check wrong data
- for (int i = 1; i < objects; i++) {
- if (isnan(F1[i]) || isnan(F2[i])) {
- objects -= 1;
- centerOfMasses.erase(centerOfMasses.begin() + i);
- F1.erase(F1.begin() + i);
- F2.erase(F2.begin() + i);
- }
- }
- for (int j = 0; j < etalons.size(); j++) {
- colors.push_back(create_color());
- }
- for (int i = 1; i < objects; i++) {
- float distance = 100.0f;
- float etalon_index;
- for (int j = 0; j < etalons.size(); j++) {
- float * etalon = etalons[j];
- float x = etalon[0] - F1[i];
- float y = etalon[1] - F2[i];
- float dist;
- dist = pow(x, 2) + pow(y, 2);
- dist = sqrt(dist);
- if (dist < distance)
- {
- distance = dist;
- etalon_index = j;
- }
- }
- float *center = centerOfMasses[i];
- cv::Vec3f color = colors[etalon_index];
- cv::circle(output, cv::Point(center[0], center[1]), 7, color, -1);
- }
- }
- 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) {
- std::vector<cv::Vec3f> colors;
- output = cv::Mat(input.size(), CV_32FC3, cv::Scalar(0.0, 0.0, 0.0));
- std::random_device rd;
- std::mt19937 eng(rd());
- std::uniform_int_distribution<> distrx(0, 1);
- std::uniform_int_distribution<> distry(0, 1);
- std::vector<float*> centroids;
- std::vector<float*> points;
- bool find_new_centroids = true;
- // check wrong data
- for (int i = 1; i < objects; i++) {
- if (isnan(F1[i]) || isnan(F2[i])) {
- objects -= 1;
- F1.erase(F1.begin() + i);
- F2.erase(F2.begin() + i);
- }
- }
- for (int i = 0; i < numOfClusters; i++) {
- float *cent = new float[2];
- cent[0] = distrx(eng);
- cent[1] = distry(eng);
- centroids.push_back(cent);
- colors.push_back(create_color());
- }
- for (int i = 1; i < objects; i++) {
- float* point = new float[2];
- point[0] = F1[i];
- point[1] = F2[i];
- points.push_back(point);
- cv::circle(output, cv::Point(F1[i] * output.cols,F2[i] * output.rows), 3, cv::Vec3f(1.0, 1.0, 1.0));
- }
- // main loop
- std::vector<int> old_assignment;
- while (find_new_centroids) {
- std::vector<int> points_assignment_idx;
- // distance for each point
- for (int i = 0; i < points.size(); i++) {
- int close_idx = 0;
- float distance = 10000.0f;
- float* point = new float[2];
- point = points[i];
- for (int j = 0; j < centroids.size(); j++) {
- float dist;
- float *cent = centroids[j];
- dist = pow(cent[0] - point[0], 2) + pow(cent[1] - point[1], 2);
- dist = sqrt(dist); // new distance
- if (dist < distance)
- {
- distance = dist;
- close_idx = j;
- }
- }
- points_assignment_idx.push_back(close_idx);
- }
- // calculate new centroids
- for (int i = 0; i < centroids.size(); i++) {
- int numOfPoints = 0;
- float meanx = 0;
- float meany = 0;
- for (int j = 0; j < points.size(); j++) {
- if (points_assignment_idx[j] == i) { // if is assigned to centroid
- numOfPoints += 1;
- float *point = new float[2];
- point = points[j];
- meanx += point[0];
- meany += point[1];
- }
- }
- if (numOfPoints > 0) {
- float* cent = new float[2];
- cent[0] = meanx / numOfPoints;
- cent[1] = meany / numOfPoints;
- centroids[i] = cent;
- }
- }
- if (old_assignment == points_assignment_idx)
- find_new_centroids = false;
- else
- old_assignment.swap(points_assignment_idx);
- stepsOverall++;
- }
- // end of loop - final centroids
- for (int i = 0; i < centroids.size(); i++) {
- float * cent = centroids[i];
- cv::circle(output, cv::Point(cent[0] * output.cols, cent[1] * output.rows), 4, colors[i], -1);
- }
- return centroids;
- }
- 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) {
- output = input.clone();
- cv::cvtColor(output, output, cv::COLOR_GRAY2BGR);
- std::vector<cv::Vec3f> colors;
- // check wrong data
- for (int i = 1; i < objects; i++) {
- if (isnan(F1[i]) || isnan(F2[i])) {
- objects -= 1;
- centerOfMasses.erase(centerOfMasses.begin() + i);
- F1.erase(F1.begin() + i);
- F2.erase(F2.begin() + i);
- }
- }
- for (int j = 0; j < kmeans.size(); j++) {
- colors.push_back(create_color());
- }
- for (int i = 1; i < objects; i++) {
- float distance = 10000.0f;
- float centroid_index = 0;
- for (int j = 0; j < kmeans.size(); j++) {
- float * kmean = kmeans[j];
- float x = kmean[0] - F1[i];
- float y = kmean[1] - F2[i];
- float dist;
- dist = pow(x, 2) + pow(y, 2);
- dist = sqrt(dist);
- if (dist < distance)
- {
- distance = dist;
- centroid_index = j;
- }
- }
- float *center = centerOfMasses[i];
- cv::Vec3f color = colors[centroid_index];
- cv::circle(output, cv::Point(center[0], center[1]), 7, color, -1);
- }
- }
- void ObjectProcessing::put_index_numbers_in_image(cv::Mat &source, std::vector<float*> centerOfMasses, std::vector<float> &F1, std::vector<float> &F2, int objects) {
- float f1 = F1[1];
- float f2 = F2[1];
- int oid = 1;
- for (int i = 1; i < objects; i++) {
- float *cn = centerOfMasses[i];
- if (round(F1[i]) == round(f1) && round(F2[i]) == round(f2))
- 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));
- else {
- oid++;
- 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));
- }
- f1 = F1[i];
- f2 = F2[i];
- }
- }
- void ObjectProcessing::get_moments_for_coordinate(cv::Mat & input, std::vector<cv::Mat>& moments, std::vector<float>& perimeters, int objects)
- {
- for (int i = 0; i < objects; i++) {
- moments.push_back(cv::Mat::zeros(cv::Size(2, 2), input.type()));
- perimeters.push_back(0.0f);
- }
- cv::Point lookForMatrix[]{
- cv::Point(1, 0),
- cv::Point(0, 1),
- cv::Point(0, -1),
- cv::Point(-1, 0)
- };
- int lookForMatrixSize = sizeof(lookForMatrix) / sizeof(cv::Point);
- for (int y = 0; y < input.rows; y++) {
- for (int x = 0; x < input.cols; x++) {
- int o_id = 0;
- if ((o_id = input.at<float>(y, x)) != 0.0f) {
- cv::Mat objectMoment = moments[o_id];
- for (int q = 0; q < objectMoment.rows; q++) {
- for (int p = 0; p < objectMoment.cols; p++) {
- objectMoment.at<float>(q, p) += pow(x, p) * pow(y, q);
- }
- }
- moments[o_id] = objectMoment;
- cv::Point point = cv::Point(x, y);
- if (point.x > 0 && point.y > 0 && point.x < input.cols - 1 && point.y < input.rows - 1) {
- int perimeterCounter = 0;
- for (int i = 0; i < lookForMatrixSize; i++) {
- cv::Point pointToCheck = point + lookForMatrix[i];
- if (input.at<float>(pointToCheck) == o_id) {
- perimeterCounter++;
- }
- }
- if (perimeterCounter != lookForMatrixSize) {
- perimeters[o_id]++;
- }
- }
- }
- }
- }
- }
- void ObjectProcessing::get_moments_center_mass(cv::Mat & input, std::vector<cv::Mat>& coordMoments, std::vector<cv::Mat>& massMoments)
- {
- for (int i = 0; i < coordMoments.size(); i++) {
- massMoments.push_back(cv::Mat::zeros(cv::Size(3, 3), input.type()));
- }
- for (int y = 0; y < input.rows; y++) {
- for (int x = 0; x < input.cols; x++) {
- int o_id = 0;
- if ((o_id = input.at<float>(y, x)) != 0.0f) {
- cv::Mat objectMoment = massMoments[o_id];
- for (int q = 0; q < objectMoment.rows; q++) {
- for (int p = 0; p < objectMoment.cols; p++) {
- float* centerOfMass = get_center(coordMoments[o_id]);
- objectMoment.at<float>(q, p) += pow(x - centerOfMass[0], p) * pow(y - centerOfMass[1], q);
- delete centerOfMass;
- }
- }
- massMoments[o_id] = objectMoment;
- }
- }
- }
- }
- 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)
- {
- for (int i = 0; i < inputMoments.size(); i++) {
- F1.push_back(get_F1(inputPerimeters[i], get_area(inputMoments[i])));
- uMin.push_back(get_uMin(inputMoments[i]));
- uMax.push_back(get_uMax(inputMoments[i]));
- F2.push_back(get_F2(uMin[i], uMax[i]));
- }
- }
- float ObjectProcessing::get_F1(float perimeter, float area)
- {
- return pow(perimeter, 2) / (100.0f * area);
- }
- float ObjectProcessing::get_F2(float uMin, float uMax)
- {
- return uMin / uMax;
- }
- float ObjectProcessing::get_uMin(cv::Mat centerOfTheMassMoment)
- {
- 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));
- }
- float ObjectProcessing::get_uMax(cv::Mat centerOfTheMassMoment)
- {
- 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));
- }
- std::vector<float> ObjectProcessing::get_areas(std::vector<cv::Mat>& inputMoments)
- {
- std::vector<float> areas;
- for (int i = 0; i < inputMoments.size(); i++) {
- areas.push_back(get_area(inputMoments[i]));
- }
- return areas;
- }
- std::vector<float*> ObjectProcessing::get_centers(std::vector<cv::Mat>& coordinateMoments)
- {
- std::vector<float*> centersOfMasses;
- for (int i = 0; i < coordinateMoments.size(); i++) {
- centersOfMasses.push_back(get_center(coordinateMoments[i]));
- }
- return centersOfMasses;
- }
- float ObjectProcessing::get_area(cv::Mat objectMoment)
- {
- return objectMoment.at<float>(0, 0);
- }
- float *ObjectProcessing::get_center(cv::Mat coordinateMoment)
- {
- float* center = new float[2];
- center[0] = coordinateMoment.at<float>(0, 1) / coordinateMoment.at<float>(0, 0);
- center[1] = coordinateMoment.at<float>(1, 0) / coordinateMoment.at<float>(0, 0);
- return center;
- }
- cv::Vec3f ObjectProcessing::create_color()
- {
- std::random_device rd;
- std::mt19937 eng(rd());
- std::uniform_int_distribution<> distr(50, 255);
- return cv::Vec3f(float(distr(eng)) / 255, float(distr(eng)) / 255, float(distr(eng)) / 255);
- }
- std::string ObjectProcessing::IntToString(int Number)
- {
- std::ostringstream ss;
- ss << Number;
- return ss.str();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement