我真的不知道它叫什么(失真或其他)
但是我想通过使用emgucv(或opencv)检测某些不同类型图像的镜头相机问题

关于使用哪种算法的任何想法将不胜感激

opencv - 检测图像问题-LMLPHP

第二张图像似乎噪声很大,但是有什么办法可以通过opencv来理解噪声吗?

opencv - 检测图像问题-LMLPHP

最佳答案

如果没有参考数据或同质性样本,通常很难做到这一点。但是,我提出了分析图像的平均SNR(Signal to Noise)比的建议。该算法根据指定的内核大小将输入图像划分为指定数量的“子图像”,以便分别对每个子图像的局部SNR进行评估。然后对每个子图像的计算出的SNR进行平均,以提供指标图像的整体SNR。

您将需要对这种方法进行详尽的测试,但是它在下面的三个图像上显示了 promise ,产生了AvgSNR

图片#1-平均SNR = 0.9

opencv - 检测图像问题-LMLPHP

图片#2-平均SNR = 7.0

opencv - 检测图像问题-LMLPHP

图片#3-平均SNR = 0.6

opencv - 检测图像问题-LMLPHP

注意:查看“干净”控制图像如何产生更高的 AvgSNR

唯一要考虑的变量是内核大小。我建议将其保持在足以支持您最小的潜在输入图像的尺寸。 30像素见方的正方形应该适合于许多图像。

我用注释将测试代码括起来:

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。当所评估的场景主要由单色的单色表面(例如服务器机房或店面)组成时,此方法将表现最佳。例如,草将包含大量纹理,因此包含“噪音”。

10-04 14:26
查看更多