sanchez 0 Жалоба Опубликовано April 20, 2017 Помогите, пожалуйста, с кодом. При склейке двух изображений получается вот это: Как можно отредактировать конечное изображение или сначала сравнять два изображения к одной яркости? #include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; int main() { // Load the images Mat image1 = imread("2.png"); Mat image2 = imread("1.png"); Mat image3; Mat gray_image1; Mat gray_image2; Mat gray_image3; // Convert to Grayscale cvtColor(image1, gray_image1, CV_RGB2GRAY); cvtColor(image2, gray_image2, CV_RGB2GRAY); imshow("first image", image1); imshow("second image", image2); if (!gray_image1.data || !gray_image2.data) { std::cout << " Error reading images " << std::endl; return -1; } //-- Step 1: Detect the keypoints using SURF Detector int minHessian = 400; SurfFeatureDetector detector(minHessian); std::vector< KeyPoint > keypoints_object, keypoints_scene; detector.detect(gray_image1, keypoints_object); detector.detect(gray_image2, keypoints_scene); //-- Step 2: Calculate descriptors (feature vectors) SurfDescriptorExtractor extractor; Mat descriptors_object, descriptors_scene; extractor.compute(gray_image1, keypoints_object, descriptors_object); extractor.compute(gray_image2, keypoints_scene, descriptors_scene); //-- Step 3: Matching descriptor vectors using FLANN matcher FlannBasedMatcher matcher; std::vector< DMatch > matches; matcher.match(descriptors_object, descriptors_scene, matches); double min_dist = 100; //-- Quick calculation of min distances between keypoints for (int i = 0; i < descriptors_object.rows; i++) { double dist = matches[i].distance; if (dist < min_dist) min_dist = dist; } //-- Use only "good" matches (i.e. whose distance is less than 3*min_dist ) std::vector< DMatch > good_matches; for (int i = 0; i < descriptors_object.rows; i++) { if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } } std::vector< Point2f > obj; std::vector< Point2f > scene; for (int i = 0; i < good_matches.size(); i++) { //-- Get the keypoints from the good matches obj.push_back(keypoints_object[good_matches[i].queryIdx].pt); scene.push_back(keypoints_scene[good_matches[i].trainIdx].pt); } // Find the Homography Matrix Mat H = findHomography(obj, scene, CV_RANSAC); // Use the Homography Matrix to warp the images Mat result; warpPerspective(image1, result, H, Size(image1.cols + image2.cols, image1.rows)); Mat half(result, Rect(0, 0, image2.cols, image2.rows)); image2.copyTo(half); imshow("Result", result); waitKey(0); return 0; } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 20, 2017 Вроде как можно перевести обе картинки в HSV, найти среднее по каналу V: v1 и v2 для каждого изображения. Затем найти отношения k1 = (v1 + v2) / 2*v1 и k2 = (v1 + v2) / 2*v2. Далее умножить каналы V обоих изображений на, соответственно, k1 и k2. И преобразовать обратно в RGB. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
sanchez 0 Жалоба Опубликовано April 20, 2017 26 минут назад, Nuzhny сказал: Вроде как можно перевести обе картинки в HSV, найти среднее по каналу V: v1 и v2 для каждого изображения. Затем найти отношения k1 = (v1 + v2) / 2*v1 и k2 = (v1 + v2) / 2*v2. Далее умножить каналы V обоих изображений на, соответственно, k1 и k2. И преобразовать обратно в RGB. спасибо, попробую) возможно чуть позже появятся вопросы Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
sanchez 0 Жалоба Опубликовано April 20, 2017 4 часа назад, Nuzhny сказал: Вроде как можно перевести обе картинки в HSV, найти среднее по каналу V: v1 и v2 для каждого изображения. Затем найти отношения k1 = (v1 + v2) / 2*v1 и k2 = (v1 + v2) / 2*v2. Далее умножить каналы V обоих изображений на, соответственно, k1 и k2. И преобразовать обратно в RGB. попробовал сделать по вашему совету: Mat image3; Mat image4; Mat hsv1, hsv2; vector<Mat> channel1; vector<Mat> channel2; // конвертируем в HSV cvtColor(image1, hsv1, CV_RGB2HSV); split(hsv1, channel1); cvtColor(image2, hsv2, CV_RGB2HSV); split(hsv2, channel2); double v1 = 0, v2 = 0; for (int i = 0; i<hsv1.rows; i++) { for (int j = 0; j<hsv1.cols; j++) { v1 += channel1[2].at<uchar>(i, j); } } for (int i = 0; i<hsv2.rows; i++) { for (int j = 0; j<hsv2.cols; j++) { v2 += channel2[2].at<uchar>(i, j); } } double v_average1 = 0, v_average2 = 0; v_average1 = v1 / (hsv1.rows * hsv1.cols); v_average2 = v2 / (hsv2.rows * hsv2.cols); double k1 = 0, k2 = 0; k1 = (v_average1 + v_average2) / (2 * v_average1); k2 = (v_average1 + v_average2) / (2 * v_average2); cout <<"v1 and v2" << v1 << " " << v2 << endl; cout <<"v_average1 and v_average2" << v_average1 << " " << v_average2 << endl; cout <<"k1 and k2" << k1 << " " << k2 << endl; for (int i = 0; i<hsv1.rows; i++) { for (int j = 0; j<hsv1.cols; j++) { channel1[2].at<uchar>(i, j) *= k1; } } for (int i = 0; i<hsv2.rows; i++) { for (int j = 0; j<hsv2.cols; j++) { channel2[2].at<uchar>(i, j) *= k2; } } bitwise_and(channel1[0], channel1[1], image3); bitwise_and(image3, channel1[2], image3); bitwise_and(channel2[0], channel2[1], image4); bitwise_and(image4, channel2[2], image4); cvtColor(image3, image1, CV_HSV2RGB); cvtColor(image4, image2, CV_HSV2RGB); и вот результат выдаёт вот такие ошибки: я нашёл, что ошибка возникает из-за того, что я преобразую обратно из HSV. но как это исправить? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 21, 2017 1. Вместо кода типа: channel1[2].at<uchar>(i, j) *= k1; Лучше писать: channel1[2].at<uchar>(i, j) = cv::saturate_cast<uchar>(k1 * channel1[2].at<uchar>(i, j)); 2. Использование bitwise_and тут в корне неправильное, надо cv::merge вызывать. 3. При конвертации, скорее всего, надо использовать не RGB, а BGR. 4. Если потом захочется ускорить всё это дело, то split/merge можно вообще убрать, а сумму считать через cv::sum. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
sanchez 0 Жалоба Опубликовано April 21, 2017 3 часа назад, Nuzhny сказал: 1. Вместо кода типа: channel1[2].at<uchar>(i, j) *= k1; Лучше писать: channel1[2].at<uchar>(i, j) = cv::saturate_cast<uchar>(k1 * channel1[2].at<uchar>(i, j)); 2. Использование bitwise_and тут в корне неправильное, надо cv::merge вызывать. 3. При конвертации, скорее всего, надо использовать не RGB, а BGR. 4. Если потом захочется ускорить всё это дело, то split/merge можно вообще убрать, а сумму считать через cv::sum. учёл ваши замечания, теперь компилируется без ошибок, но данный способ не помог выравнять яркость #include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; using namespace std; int main() { // Load the images Mat image1 = imread("2.png"); Mat image2 = imread("1.png"); Mat image3; Mat image4; Mat gray_image1; Mat gray_image2; Mat gray_image3; Mat hsv1, hsv2; vector<Mat> channel1; vector<Mat> channel2; // конвертируем в HSV cvtColor(image1, hsv1, CV_BGR2HSV); split(hsv1, channel1); imshow("h channel", channel1[2]); cvtColor(image2, hsv2, CV_BGR2HSV); split(hsv2, channel2); imshow("h channel1", channel2[2]); double v1 = 0, v2 = 0; for (int i = 0; i<hsv1.rows; i++) { for (int j = 0; j<hsv1.cols; j++) { v1 += channel1[2].at<uchar>(i, j); } } for (int i = 0; i<hsv2.rows; i++) { for (int j = 0; j<hsv2.cols; j++) { v2 += channel2[2].at<uchar>(i, j); } } double v_average1 = 0, v_average2 = 0; v_average1 = v1 / (hsv1.rows * hsv1.cols); v_average2 = v2 / (hsv2.rows * hsv2.cols); double k1 = 0, k2 = 0; k1 = (v_average1 + v_average2) / (2 * v_average1); k2 = (v_average1 + v_average2) / (2 * v_average2); cout <<"v1 and v2: " << v1 << " " << v2 << endl; cout << "v_average1 and v_average2: " << v_average1 << " " << v_average2 << endl; cout << "k1 and k2: " << k1 << " " << k2 << endl; for (int i = 0; i<hsv1.rows; i++) { for (int j = 0; j<hsv1.cols; j++) { channel1[2].at<uchar>(i, j) = cv::saturate_cast<uchar>(k1 * channel1[2].at<uchar>(i, j)); } } for (int i = 0; i<hsv2.rows; i++) { for (int j = 0; j<hsv2.cols; j++) { channel2[2].at<uchar>(i, j) = cv::saturate_cast<uchar>(k2 * channel2[2].at<uchar>(i, j)); } } merge(channel1, image3); merge(channel2, image4); imshow("first image11", image3); imshow("first image12", image4); cvtColor(image3, image1, CV_HSV2BGR); cvtColor(image4, image2, CV_HSV2BGR); // Convert to Grayscale cvtColor(image1, gray_image1, CV_RGB2GRAY); cvtColor(image2, gray_image2, CV_RGB2GRAY); imshow("first image", image1); imshow("second image", image2); if (!gray_image1.data || !gray_image2.data) { std::cout << " Error reading images " << std::endl; return -1; } //-- Step 1: Detect the keypoints using SURF Detector int minHessian = 400; SurfFeatureDetector detector(minHessian); std::vector< KeyPoint > keypoints_object, keypoints_scene; detector.detect(gray_image1, keypoints_object); detector.detect(gray_image2, keypoints_scene); //-- Step 2: Calculate descriptors (feature vectors) SurfDescriptorExtractor extractor; Mat descriptors_object, descriptors_scene; extractor.compute(gray_image1, keypoints_object, descriptors_object); extractor.compute(gray_image2, keypoints_scene, descriptors_scene); //-- Step 3: Matching descriptor vectors using FLANN matcher FlannBasedMatcher matcher; std::vector< DMatch > matches; matcher.match(descriptors_object, descriptors_scene, matches); double min_dist = 100; //-- Quick calculation of min distances between keypoints for (int i = 0; i < descriptors_object.rows; i++) { double dist = matches[i].distance; if (dist < min_dist) min_dist = dist; } //-- Use only "good" matches (i.e. whose distance is less than 3*min_dist ) std::vector< DMatch > good_matches; for (int i = 0; i < descriptors_object.rows; i++) { if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } } std::vector< Point2f > obj; std::vector< Point2f > scene; for (int i = 0; i < good_matches.size(); i++) { //-- Get the keypoints from the good matches obj.push_back(keypoints_object[good_matches[i].queryIdx].pt); scene.push_back(keypoints_scene[good_matches[i].trainIdx].pt); } // Find the Homography Matrix Mat H = findHomography(obj, scene, CV_RANSAC); // Use the Homography Matrix to warp the images Mat result; warpPerspective(image1, result, H, Size(image1.cols + image2.cols, image1.rows)); Mat half(result, Rect(0, 0, image2.cols, image2.rows)); image2.copyTo(half); imshow("Result", result); waitKey(0); return 0; } это я что-то неправильно сделал, или же метод просто не подходит? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 21, 2017 1. Ты делаешь вывод HSV изображений: imshow("first image11", image3); Imshow("first image12", image4); OpenCV это не умеет и выводит их, считая, что они RGB. Вывод надо делать после конвертации. 2. Я бы сделал как-то так: // Load the images cv::Mat image1 = cv::imread("2.png"); cv::Mat image2 = cv::imread("1.png"); // конвертируем в HSV cv::Mat hsv1; cv::cvtColor(image1, hsv1, CV_BGR2HSV); cv::Mat hsv2; cv::cvtColor(image2, hsv2, CV_BGR2HSV); cv::Scalar v1 = cv::sum(hsv1) / (hsv1.rows * hsv1.cols); cv::Scalar v2 = cv::sum(hsv2) / (hsv1.rows * hsv1.cols); double k1 = (v1[2] + v2[2]) / (2 * v1[2]); double k2 = (v1[2] + v2[2]) / (2 * v2[2]); std::cout << "v_average1 and v_average2: " << v1[2] << " " << v2[2] << std::endl; std::cout << "k1 and k2: " << k1 << " " << k2 << std::endl; for (int y = 0; y < hsv1.rows; ++y) { uchar* p1 = hsv1.ptr(y); uchar* p2 = hsv2.ptr(y); for (int x = 0; x < hsv1.cols; ++x) { p1[2] = cv::saturate_cast(k1 * p1[2]); p2[2] = cv::saturate_cast(k2 * p2[2]); p1 += 3; p2 += 3; } } cv::imshow("first image original", image1); cv::imshow("second image original", image2); cv::Mat image12; cv::Mat image22; cv::cvtColor(hsv1, image12, CV_HSV2BGR); cv::cvtColor(hsv2, image22, CV_HSV2BGR); cv::imshow("first image new", image12); cv::imshow("second image new", image22); // Узнаем, как сильно стали различаться каналы в RGB cv::Mat diff1; cv::absdiff(image1, image12, diff1); cv::Mat diff2; cv::absdiff(image2, image22, diff2); cv::Scalar d1 = cv::sum(diff1); cv::Scalar d2 = cv::sum(diff2); std::cout << "diff1 and diff2: " << d1 << " " << d2 << std::endl; 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 21, 2017 Если что в opencv есть http://docs.opencv.org/2.4/modules/stitching/doc/introduction.html Вам нужны части exposure compensation и blending. https://github.com/opencv/opencv/blob/c17afe0fab61bb11452b36fb94eaeb405293e086/samples/cpp/stitching_detailed.cpp 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 21, 2017 25 minutes ago, mrgloom said: Если что в opencv есть Ну, если можно использовать опенсивишный stitching, то вообще всё это не нужно - просто его использовать и всё. 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
sanchez 0 Жалоба Опубликовано April 21, 2017 1 час назад, Nuzhny сказал: Ну, если можно использовать опенсивишный stitching, то вообще всё это не нужно - просто его использовать и всё. если вам не сложно, не могли бы помочь с кодом, или поподробней рассказать что с этим stitching надо делать Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 21, 2017 Так тебе mrgloom выше ссылку дал на стандартный пример. Это и есть код. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
sanchez 0 Жалоба Опубликовано April 21, 2017 5 часов назад, Nuzhny сказал: Так тебе mrgloom выше ссылку дал на стандартный пример. Это и есть код. Простите за мою откровенную тупость(первый раз сталкиваюсь с opencv), просто я никак не могу разобраться с этим примером, и уж тем более как его применить к моей работе. если поможете, буду очень благодарен Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Nuzhny 243 Жалоба Опубликовано April 23, 2017 Разобраться в исходниках примера или в алгоритмах? Если у тебя скомпилированы примеры, то просто запускай его с различными опциями (они описаны). Если примеры не скомпилированы, то скомпилируй. Так, запуская на своих данных с разными опциями, ты поймёшь что и как влияет на результат. Это самый лучший способ разобраться, только потом есть смысл углубляться в теорию. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
sanchez 0 Жалоба Опубликовано May 3, 2017 а есть какой-то способ (без stiching), чтобы обработать изображения. Может как то обработать уже результирующее изображении? просто нужно, чтобы алгоритм(код) склейки оставался прежним(как я скидывал в самом начале) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано May 3, 2017 Можно и не выравнивать, а просто швы блендингом замазать. Делаете маску с элементами 0 для первого изображения, 1 для второго, размываете, и получаете результат как res=mask.mul(I_1)+(1-mask).mul(I_2). Нужно делать поканально, все матрицы преобразовать к CV_32FC1. Получим плавный переход в месте стыка. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
sanchez 0 Жалоба Опубликовано May 3, 2017 1 час назад, Smorodov сказал: Можно и не выравнивать, а просто швы блендингом замазать. Делаете маску с элементами 0 для первого изображения, 1 для второго, размываете, и получаете результат как res=mask.mul(I_1)+(1-mask).mul(I_2). Нужно делать поканально, все матрицы преобразовать к CV_32FC1. Получим плавный переход в месте стыка. если не сложно, можно чуть поподробней как это сделать, а то с реализацией у меня большие проблемы. я понял только создание масок(и то не уверен об этом ли вы говорили) Mat mask1 = Mat::zeros(image1.rows, image1.cols, CV_32FC1); Mat mask2 = Mat::ones(image2.rows, image2.cols, CV_32FC1); Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано May 3, 2017 Что то вроде этого: http://stackoverflow.com/questions/21795643/image-edge-smoothing-with-opencv/21801424#21801424 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах