我真的不知道它叫什么(失真或其他)
但是我想通过使用emgucv(或opencv)检测某些不同类型图像的镜头相机问题
关于使用哪种算法的任何想法将不胜感激
第二张图像似乎噪声很大,但是有什么办法可以通过opencv来理解噪声吗?
最佳答案
如果没有参考数据或同质性样本,通常很难做到这一点。但是,我提出了分析图像的平均SNR(Signal to Noise)比的建议。该算法根据指定的内核大小将输入图像划分为指定数量的“子图像”,以便分别对每个子图像的局部SNR进行评估。然后对每个子图像的计算出的SNR进行平均,以提供指标图像的整体SNR。
您将需要对这种方法进行详尽的测试,但是它在下面的三个图像上显示了 promise ,产生了AvgSNR
;
图片#1-平均SNR = 0.9
图片#2-平均SNR = 7.0
图片#3-平均SNR = 0.6
注意:查看“干净”控制图像如何产生更高的 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
。当所评估的场景主要由单色的单色表面(例如服务器机房或店面)组成时,此方法将表现最佳。例如,草将包含大量纹理,因此包含“噪音”。