Как применить пользовательские фильтры к изображению?

#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.