Обнаружение проблем с изображением - PullRequest
2 голосов
/ 25 мая 2020

Я действительно не знаю, как это называется (искажение или что-то еще), но я хотел бы обнаружить проблемы с камерой объектива для некоторых разных типов изображений с помощью emgucv (или opencv)

Любые идеи по поводу какие алгоритмы следует использовать

Distortion

Кажется, что второе изображение имеет высокий уровень шума, но есть ли способ понять высокий уровень шума с помощью opencv?

high noise

Ответы [ 2 ]

2 голосов
/ 31 мая 2020

Этого очень трудно добиться без справочных данных или образца однородности. Однако я разработал рекомендацию по анализу отношения среднего отношения сигнал / шум ( сигнал / шум ) изображения. Алгоритм делит входное изображение на заданное количество «субизображений» на основе заданного размера ядра, чтобы независимо оценивать их для локального SNR. Вычисленные SNR для каждого субизображения затем усредняются для получения индикатора для глобального SNR изображения.

Вам нужно будет тщательно протестировать этот подход, однако он показывает многообещающие результаты на следующих трех изображениях, создавая AvgSNR;

Изображение # 1 - AvgSNR = 0,9

Image 1

Изображение # 2 - AvgSNR = 7,0

Image 2

Изображение №3 - AvgSNR = 0,6

Image 3

ПРИМЕЧАНИЕ: Посмотрите, как "чистый" контрольный образ дает намного больше AvgSNR.

Единственная переменная, которую следует учитывать, - это размер ядра. Я бы рекомендовал оставить это значение на размер, который будет поддерживать даже самые маленькие из ваших потенциальных входных изображений. Квадрат 30 пикселей, вероятно, будет подходящим для r много изображений.

Я прилагаю свой тестовый код с аннотацией:

class Program
{
    static void Main(string[] args)
    {
        // List of file names to load.
        List<string> fileNames = new List<string>()
        {
            "IifXZ.png",
            "o1z7p.jpg",
            "NdQtj.jpg"
        };

        // For each image
        foreach (string fileName in fileNames)
        {
            // Determine local file path
            string path = Path.Combine(Environment.CurrentDirectory, @"TestImages\", fileName);
            // Load the image
            Image<Bgr, byte> inputImage = new Image<Bgr, byte>(path);

            // Compute the AvgSNR with a kernel of 30x30
            Console.WriteLine(ComputeAverageSNR(30, inputImage.Convert<Gray, byte>()));

            // Display the image
            CvInvoke.NamedWindow("Test");
            CvInvoke.Imshow("Test", inputImage);
            while (CvInvoke.WaitKey() != 27) { }
        }

        // Pause for evaluation
        Console.ReadKey();
    }

    static double ComputeAverageSNR(int kernelSize, Image<Gray, byte> image)
    {
        // Calculate the number of sub-divisions given the kernel size
        int widthSubDivisions, heightSubDivisions;
        widthSubDivisions = (int)Math.Floor((double)image.Width / kernelSize);
        heightSubDivisions = (int)Math.Floor((double)image.Height / kernelSize);
        int totalNumberSubDivisions = widthSubDivisions * widthSubDivisions;
        Rectangle ROI = new Rectangle(0, 0, kernelSize, kernelSize);

        double avgSNR = 0;
        // Foreach sub-divions, calculate the SNR and sum to the avgSNR
        for (int v = 0; v < heightSubDivisions; v++)
        {
            for (int u = 0; u < widthSubDivisions; u++)
            {
                // Iterate the sub-division position
                ROI.Location = new Point(u * kernelSize, v * kernelSize);
                // Calculate the SNR of this sub-division
                avgSNR += ComputeSNR(image.GetSubRect(ROI));
            }
        }

        avgSNR /= totalNumberSubDivisions;

        return avgSNR;
    }

    static double ComputeSNR(Image<Gray, byte> image)
    {
        // Local varibles
        double mean, sigma, snr;

        // Calculate the mean pixel value for the sub-division
        int population = image.Width * image.Height;
        mean = CvInvoke.Sum(image).V0 / population;

        // Calculate the Sigma of the sub-division population
        double sumDeltaSqu = 0;
        for (int v = 0; v < image.Height; v++)
        {
            for (int u = 0; u < image.Width; u++)
            {
                sumDeltaSqu += Math.Pow(image.Data[v, u, 0] - mean, 2);
            }
        }
        sumDeltaSqu /= population;
        sigma = Math.Pow(sumDeltaSqu, 0.5);

        // Calculate and return the SNR value
        snr = sigma == 0 ? mean : mean / sigma;
        return snr;
    }
}

ПРИМЕЧАНИЕ: Без ссылки невозможно различить естественную дисперсию / точность и «шум». Например, фон с высокой текстурой или сцена с несколькими однородными областями даст высокий AvgSNR. Этот подход будет работать лучше всего, когда оцениваемая сцена состоит в основном из простых одноцветных поверхностей, таких как серверная или магазин. Например, трава может содержать большое количество текстуры и, следовательно, «шума».

1 голос
/ 31 мая 2020

Альтернативный метод - рассмотреть возможность оценки ваших изображений в частотной области после преобразования Фурье. В основном, предоставленные вами примеры шума представляют собой изображения, содержащие нежелательный высокочастотный контент. Проведите БПФ и оцените изображения, нарушающие порог для высоких частот. Вот пример БПФ с Эмгу: БПФ с Эмгу

...