Мне нужна помощь с моим проектом. Я читаю цветное изображение (исходное изображение) с диска, и моя задача — применить размытие к этому изображению только там, где функция Canny обнаруживает края в этом изображении. Таким образом, обнаружение краев происходит без проблем, как вы можете видеть на прикрепленных изображениях (верхний левый угол изображения — Edge Image).
Я применил 4 шага от связанных вопросов
этот а также этот.
Вероятно, шаги 1-3 являются правильными, как вы можете видеть на прилагаемом изображении. Первое изображение показывает обнаруженные края, второе показывает расширенное предыдущее изображение, третье изображение показывает размытое второе изображение и скопированное исходное изображение в это изображение. Но на последнем шаге я хочу скопировать это изображение в конечное изображение (исходное изображение), чтобы добиться того, что обнаруженные края будут размыты. Но когда я использую функцию copyTo из библиотеки OpenCV, результат не имеет размытых краев, которые обнаруживает функция Canny, как вы можете видеть на рисунке Результат (изображение в правом нижнем углу). Можете ли вы помочь мне, пожалуйста, что я делаю плохо?
#include <cstdlib>
#include <iostream>
#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
Mat src, src_gray;
Mat detected_edges;
Mat blurred;
int edgeTresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
char* window_name = "Edge Image";
char* window_name2 = "Dilated";
char* window_name3 = "Blurred";
char* window_name4 = "Result";
void CannyThreshold(int, void*)
{
//reducing noise
blur(src_gray, detected_edges, Size(3,3));
//Canny function for detection of edges
Canny(detected_edges,detected_edges, lowThreshold,lowThreshold*ratio, kernel_size);
//show detected edges in source image
imshow(window_name, detected_edges);
//4 steps from stack owerflow
dilate(detected_edges, blurred, Mat()); //1
imshow(window_name2, blurred);
src.copyTo(blurred,blurred); //2
blur(blurred, blurred ,Size(10,10)); //3
imshow(window_name3, blurred);
//here can by a problem when I copy image from step 3 to source image with detected_edges mask.
blurred.copyTo(src,detected_edges); //4
imshow(window_name4, src); //final image
}
int main(int argc, char *argv[])
{
//reading image
src = cv::imread("/home/ja/FCS02/FCS02_3/imageReading/drevo.png");
if(!src.data)
return -1;
//convert to gray
cvtColor(src,src_gray,CV_BGR2GRAY);
//windows for showing each step image
namedWindow(window_name,CV_WINDOW_NORMAL);
namedWindow(window_name2,CV_WINDOW_NORMAL);
namedWindow(window_name3,CV_WINDOW_NORMAL);
namedWindow(window_name4,CV_WINDOW_NORMAL);
//trackbar
createTrackbar("Min Threshold:",window_name, &lowThreshold, max_lowThreshold,CannyThreshold);
//detection of edges
CannyThreshold(0,0);
cv::waitKey(300000);
return EXIT_SUCCESS;
}
Исходное изображение, где я хочу размыть только края
Это изображение показывает, что я хочу
Большое спасибо всем за вашу помощь и советы.
Когда вы копируете размытый край исходного изображения, вы используете неправильную маску. detected_edges
содержит выходные данные детектора Канни (только несколько разреженных пикселей). Ненулевые пиксели, если маска указывает, какие пиксели исходного изображения могут быть скопированы в место назначения. Изображение blurred
содержит только размытый край, а остальные пиксели черного цвета. Поэтому я думаю, что вы можете напрямую использовать его в качестве маски для копии.
blurred.copyTo(src, blurred); //4
Имейте в виду, что маска должна быть типа CV_8U. Кажется, что в вашем примере это так. Если нет, вы можете использовать следующий код, чтобы создать изображение черного цвета, кроме случаев, когда пиксели в blurred
не являются нулевыми
blurred.copyTo(src, (blurred != 0)); //4
Других решений пока нет …