/
Dev_Devil
/
ComputerVision
Обзор
Документация
Войти
/
Dev_Devil
/
ComputerVision
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
Matveev_A_I_OpenCV_2022/part9/cpp/src/Main.cpp
347 строк
12 KB
6ap6apuk
upload src files
14 дек 2025, 11:31
14 дек 2025, 11:31
5290ccb
Код
Авторство
О чём код?
#include <iostream> #include <vector> #include <cmath> #include <iomanip> #include <numeric> #include <algorithm> #include <functional> #include <Windows.h> #include "opencv2/opencv.hpp" #define _USE_MATH_DEFINES #include <math.h> cv::Mat shelf(const cv::Mat& img, int k = 120) { cv::Mat result = img.clone(); int rows = img.rows; int cols = img.cols; for (int i = 0; i < rows; ++i) { cv::Vec3b base_color = img.at<cv::Vec3b>(i, 0); for (int j = 0; j < cols; ++j) { cv::Vec3b current_pixel = img.at<cv::Vec3b>(i, j); if (abs(current_pixel[0] - base_color[0]) <= k && abs(current_pixel[1] - base_color[1]) <= k && abs(current_pixel[2] - base_color[2]) <= k) { result.at<cv::Vec3b>(i, j) = cv::Vec3b(0, 0, 0); } } } return result; } cv::Mat background_white(const cv::Mat& img) { cv::Mat hsv_image; cv::cvtColor(img, hsv_image, cv::COLOR_BGR2HSV); cv::Scalar lower_white(0, 0, 250); cv::Scalar upper_white(179, 30, 255); cv::Mat mask_white; cv::inRange(hsv_image, lower_white, upper_white, mask_white); cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); cv::dilate(mask_white, mask_white, kernel, cv::Point(-1, -1), 1); cv::Mat result = img.clone(); result.setTo(cv::Scalar(0, 0, 0), mask_white); return result; } cv::Mat segment(const cv::Mat& img) { cv::Mat result = img.clone(); cv::Mat gray; cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); cv::Mat im_bw; cv::threshold(gray, im_bw, 30, 255, cv::THRESH_BINARY); cv::imshow("im_bw", im_bw); cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 4)); cv::Mat opening; cv::morphologyEx(im_bw, opening, cv::MORPH_OPEN, kernel, cv::Point(-1, -1), 1); cv::Mat sure_bg; cv::dilate(opening, sure_bg, kernel, cv::Point(-1, -1), 1); cv::Mat dist_transform; cv::distanceTransform(opening, dist_transform, cv::DIST_L2, 3); cv::Mat sure_fg; double max_val; cv::minMaxLoc(dist_transform, nullptr, &max_val); cv::threshold(dist_transform, sure_fg, 0.01 * max_val, 255, cv::THRESH_BINARY); sure_fg.convertTo(sure_fg, CV_8U); cv::Mat unknown; cv::Canny(sure_bg, unknown, 700, 100, 3); cv::imshow("Canny", unknown); cv::Mat markers; int num_components = cv::connectedComponents(sure_fg, markers); markers = markers + 1; markers.setTo(0, unknown == 255); cv::watershed(result, markers); result.setTo(cv::Scalar(255, 0, 0), markers == -1); return result; } cv::Mat find_object(const cv::Mat& img, const cv::Mat& object, double threshold) { cv::Mat result = img.clone(); cv::Mat img_gray; cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); cv::Mat object_gray; if (object.channels() == 3) { cv::cvtColor(object, object_gray, cv::COLOR_BGR2GRAY); } else { object_gray = object.clone(); } int h1 = object_gray.rows; int w1 = object_gray.cols; double wr = 77 * h1 / 160.0; cv::Mat template_img; cv::resize(object_gray, template_img, cv::Size(static_cast<int>(wr), 160)); int w = template_img.cols; int h = template_img.rows; cv::Mat res; cv::matchTemplate(img_gray, template_img, res, cv::TM_CCOEFF_NORMED); for (int i = 0; i < res.rows; i++) { for (int j = 0; j < res.cols; j++) { if (res.at<float>(i, j) >= threshold) { cv::Point pt(j, i); cv::rectangle(result, pt, cv::Point(pt.x + w, pt.y + h), cv::Scalar(2, 0, 255), 2); } } } return result; } void detect_objects(const cv::Mat& img, std::vector<std::vector<cv::Point>>& filtered_contours, std::vector<cv::Rect>& object_rects, int min_area = 1000, int max_area = 20000) { cv::Mat gray; cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); cv::Mat binary; cv::threshold(gray, binary, 30, 255, cv::THRESH_BINARY); std::vector<std::vector<cv::Point>> contours; cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); filtered_contours.clear(); object_rects.clear(); for (const auto& contour : contours) { double area = cv::contourArea(contour); if (area > min_area && area < max_area) { filtered_contours.push_back(contour); cv::Rect rect = cv::boundingRect(contour); object_rects.push_back(rect); } } } cv::Mat visualize_results(const cv::Mat& img, const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Rect>& object_rects) { cv::Mat result_img = img.clone(); cv::drawContours(result_img, contours, -1, cv::Scalar(0, 255, 0), 2); for (size_t i = 0; i < object_rects.size(); ++i) { const cv::Rect& rect = object_rects[i]; cv::rectangle(result_img, rect, cv::Scalar(255, 0, 0), 2); std::string text = "Obj " + std::to_string(i + 1); cv::putText(result_img, text, cv::Point(rect.x, rect.y - 10), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255, 0, 0), 1); } return result_img; } struct ObjectFeatures { int object_id; double area; double perimeter; int width; int height; double aspect_ratio; double extent; double equi_diameter; double m00; double m10; double m01; double m11; double m20; double m02; }; ObjectFeatures compute_features(const std::vector<cv::Point>& contour, const cv::Mat& img) { ObjectFeatures features; features.area = cv::contourArea(contour); features.perimeter = cv::arcLength(contour, true); cv::Rect bounding_rect = cv::boundingRect(contour); features.width = bounding_rect.width; features.height = bounding_rect.height; if (features.height != 0) { features.aspect_ratio = static_cast<double>(features.width) / features.height; } else { features.aspect_ratio = 0; } double rect_area = features.width * features.height; if (rect_area != 0) { features.extent = features.area / rect_area; } else { features.extent = 0; } features.equi_diameter = std::sqrt(4 * features.area / M_PI); cv::Moments M = cv::moments(contour); features.m00 = M.m00; features.m10 = M.m10; features.m01 = M.m01; features.m11 = M.m11; features.m20 = M.m20; features.m02 = M.m02; return features; } std::vector<ObjectFeatures> create_feature_table(const std::vector<std::vector<cv::Point>>& contours, const cv::Mat& img) { std::vector<ObjectFeatures> feature_table; for (size_t i = 0; i < contours.size(); ++i) { ObjectFeatures features = compute_features(contours[i], img); features.object_id = i + 1; feature_table.push_back(features); } return feature_table; } void print_feature_table(const std::vector<ObjectFeatures>& feature_table) { std::cout << "ID\tArea\tPerimeter\tWidth\tHeight\tAspect Ratio\tExtent\tEqui Diameter" << std::endl; std::cout << "----------------------------------------------------------------------------------------" << std::endl; for (const auto& features : feature_table) { std::cout << features.object_id << "\t" << features.area << "\t" << features.perimeter << "\t\t" << features.width << "\t" << features.height << "\t" << features.aspect_ratio << "\t\t" << features.extent << "\t" << features.equi_diameter << std::endl; } } class NeuralNetwork { private: std::vector<double> weights_; public: NeuralNetwork(const std::vector<double>& weights) : weights_(weights) {} std::vector<std::vector<double>> standardizeFeatures(const std::vector<std::vector<double>>& features) { if (features.empty()) return {}; size_t num_features = features[0].size(); size_t num_objects = features.size(); std::vector<std::vector<double>> standardized(num_objects, std::vector<double>(num_features)); for (size_t i = 0; i < num_features; ++i) { std::vector<double> feature_column; for (const auto& obj : features) { feature_column.push_back(obj[i]); } double mean = std::accumulate(feature_column.begin(), feature_column.end(), 0.0) / feature_column.size(); double sum_sq = std::accumulate(feature_column.begin(), feature_column.end(), 0.0, [mean](double acc, double val) { return acc + (val - mean) * (val - mean); }); double std_dev = std::sqrt(sum_sq / feature_column.size()); for (size_t j = 0; j < num_objects; ++j) { standardized[j][i] = (std_dev > 0) ? (features[j][i] - mean) / std_dev : 0; } } return standardized; } double computeOutput(const std::vector<double>& inputs) { if (inputs.size() != weights_.size()) { throw std::invalid_argument("Input size must match weights size"); } return std::inner_product(inputs.begin(), inputs.end(), weights_.begin(), 0.0); } std::vector<double> computeMarkers(const std::vector<std::vector<double>>& features) { std::vector<std::vector<double>> standardized = standardizeFeatures(features); std::vector<double> markers; for (const auto& obj_features : standardized) { markers.push_back(computeOutput(obj_features)); } return markers; } }; int main() { cv::Mat objectToFind = cv::imread("object3_small.png"); cv::Mat img = cv::imread("posuda3_line_clear.png"); if (img.empty() || objectToFind.empty()) { std::cout << "Could not open or find the image!" << std::endl; return -1; } cv::resize(img, img, cv::Size(800, 300)); cv::Mat imr = background_white(img); cv::imshow("Original", imr); cv::Mat segmented = segment(imr); cv::imshow("Segmented", segmented); cv::Mat found_object = find_object(imr, objectToFind, 0.82); cv::imshow("Object to find", objectToFind); cv::imshow("Found_object", found_object); std::vector<std::vector<cv::Point>> contours; std::vector<cv::Rect> object_rects; detect_objects(imr, contours, object_rects); std::cout << "Found objects: " << contours.size() << std::endl; std::vector<ObjectFeatures> feature_table = create_feature_table(contours, imr); print_feature_table(feature_table); cv::Mat result_img = visualize_results(imr, contours, object_rects); cv::imshow("Detected Objects", result_img); cv::waitKey(0); std::vector<std::vector<double>> features = { {5431.5, 410.9, 35, 178, 0.2, 0.87, 83.2, 5431.5, 1012247.33, 651775.17, 121467222.38}, {7951, 458.1, 47, 193, 0.24, 0.88, 100.6, 7951, 1380571.17, 5878092.33, 1020561382.42}, {10792.5, 511.6, 63, 192, 0.33, 0.89, 117.2, 10792.5, 1902824.67, 4320931, 761700333.04}, {7423, 686.3, 76, 208, 0.37, 0.47, 97.2, 7423, 1390940.5, 4892416.17, 916099347.92}, {14827, 568.5, 79, 208, 0.38, 0.9, 137.4, 14827, 2511958.5, 8431409.17, 1428616244.75}, {11293.5, 553, 72, 222, 0.32, 0.71, 119.9, 11293.5, 2010810.67, 3586408.67, 638407288.38}, {9233, 582, 61, 224, 0.27, 0.68, 108.4, 9233, 1676932.5, 1697238.33, 308521602.08}, {7473, 513.5, 36, 224, 0.16, 0.93, 97.5, 7473, 1164186.83, 1837083.17, 286225331.67}, {10299.5, 548.7, 64, 233, 0.27, 0.69, 114.5, 10299.5, 1776401.33, 4969496.17, 857090912.46}, {12721, 587.8, 76, 233, 0.33, 0.72, 127.3, 12721, 2118265.17, 707117.83, 117389024.42} }; std::vector<double> weights = {0.15, 0.14, 0.12, 0.12, 0.10, 0.10, 0.09, 0.06, 0.04, 0.04, 0.04}; NeuralNetwork nn(weights); std::vector<double> markers = nn.computeMarkers(features); for (size_t i = 0; i < markers.size(); ++i) { std::cout << "Object: " << (i + 1) << ": marker = " << std::fixed << std::setprecision(2) << markers[i] << std::endl; } return 0; return 0; }