Detect Image Problems

Viewed 250

I really don't know what it is called (distortion or something else) But I would like to detect lens camera problems for some different types of images by using emgucv (or opencv)

Any ideas about which algorithms to use would be appreciated

Distortion

Second image seems to have high noise, but is there any way to understand high noise via opencv?

high noise

2 Answers

This is very difficult to achieve generically without reference data or a homogeneity sample. However, I have developed a recommendation analyzing the Average SNR (Signal to Noise) ratio of the image. The algorithm divides the input image into a specified number of "sub images' based on a specified kernel size in order to evaluate each independently for local SNR. The computed SNRs for each sub image are then mean averaged to provide an indicator for the global SNR of the image.

You will need to test this approach exhaustively, however it shows promise on the following three images, producing AvgSNR;

Image #1 - AvgSNR = 0.9

Image 1

Image #2 - AvgSNR = 7.0

Image 2

Image #3 - AvgSNR = 0.6

Image 3

NOTE: See how the "clean" control image produces a much higher AvgSNR.

The only variable to consider is the kernel size. I would recommend keeping this at a size that will support will even the smallest of your potential input images. 30 pixels square should likely be appropriate for many images.

I enclose my test code with annotation:

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;
    }
}

NOTE: Without a reference, it is not possible to differentiate between natural variance/fidelity and "noise". For example, a highly texture background, or a scene with few homogeneous regions will yield a high AvgSNR. This approach will perform best when the evaluated scene consists mostly of plain, mono-color surfaces, such as the server room or shop front. Grass for example would contain a large amount of texture and therefore "noise".

An alternative method is to consider evaluating your images in the frequency domain following a Fourier transform. Principally, the noise examples you have provided are images containing unwanted, high frequency content. Conduct FFT and evaluate for images violating a threshold for high frequencies. Here you will from an example of FFT with Emgu: FFT with Emgu

Related