#c #opencv #image-processing
#c #opencv #обработка изображений
Вопрос:
Я использую OpenCV4 в Ubuntu 20.04 LTS на WSL XServer для графического интерфейса.
Я хочу создать пользовательские ядра сверточных фильтров и применить их к моему изображению. это код, который я написал для него:
cv::Mat filter2D(cv::Mat input, cv::Mat filter)
{
using namespace cv;
Mat dst = input.clone();
//cout << " filter data successfully found. Rows:" << filter.rows << " cols:" << filter.cols << " channels:" << filter.channels() << "n";
//cout << " input data successfully found. Rows:" << input.rows << " cols:" << input.cols << " channels:" << input.channels() << "n";
for (int i = 0-(filter.rows/2);i<input.rows-(filter.rows/2);i )
{
for (int j = 0-(filter.cols/2);j<input.cols-(filter.cols/2);j )
{ //adding k and l to i and j will make up the difference and allow us to process the whole image
float filtertotal = 0;
for (int k = 0; k < filter.rows;k )
{
for (int l = 0; l < filter.rows;l )
{
if(i k >= 0 amp;amp; i k < input.rows amp;amp; j l >= 0 amp;amp; j l < input.cols)
{ //don't try to process pixels off the edge of the map
float a = input.at<uchar>(i k,j l);
float b = filter.at<float>(k,l);
float product = a * b;
filtertotal = product;
}
}
}
//filter all proccessed for this pixel, write it to dst
dst.at<uchar>(i (filter.rows/2),j (filter.cols/2)) = filtertotal;
}
}
return dst;
}
int main(int argc, char** argv)
{
// Declare variables
cv::Mat_<float> src;
const char* window_name = "filter2D Demo";
// Loads an image
src = cv::imread("fapan.png", cv::IMREAD_GRAYSCALE ); // Load an image
if( src.empty() )
{
printf(" Error opening imagen");
return EXIT_FAILURE;
}
static float x[3][3] = {
{-1, -1, -1},
{-1, 8, -1},
{-1, -1, -1}
};
cv::Mat kernel(3,3, CV_16FC1, x);
// Apply filter
filter2D(src, kernel);
cv::imshow( window_name, src );
cv::waitKey(0);
return EXIT_SUCCESS;
}
проблема в том, что выходное изображение выглядит следующим образом.
как вы можете видеть, не только края белые, но и внутри него тоже белые.
Комментарии:
1. масштабируйте изображение в диапазоне 0-255 для байтового типа данных без знака и от 0 до 1 для типа данных с плавающей точкой. в противном случае ваше изображение будет белым
2. @user8190410 спасибо за помощь. я новичок. можете ли вы дать мне больше информации и рассказать, как я могу это сделать?
3. Что такое входное изображение?
4. Функция Лапласа выдает значения за пределами входного диапазона, включая отрицательные значения. Вам нужно применить линейное отображение, чтобы привести значения результата в стандартный диапазон, который
cv::imshow
ожидает.5. @CrisLuengo Я сделал это
src.convertTo(dst, CV_8UC1);
, но когда я делаю это перед imshow, вместо отображения краев отображается только обычное изображение в оттенках серого
Ответ №1:
Выходные данные, которые вы опубликовали для входного кода, верны, поскольку вы применяете обычный фильтр к изображению.
Это может привести к небольшому размытию или повышению резкости, но это никогда не приведет к полному обнаружению краев.
Чтобы обнаружить только края вдоль изображений, вы должны применить лапласиан вдоль определенного направления. https://www.l3harrisgeospatial.com/docs/LaplacianFilters.html#:~:text=A Laplacian filter is an,an edge or continuous progression. (Ссылка с некоторой информацией), которая является производной от изображения, она только обнаружит изменение.
Я рекомендую вам сделать это в matlab image processing toolbox.