所以这是我的问题
我使用扫描仪扫描灰度对象并将其转换为JPEG格式,以便通过C#程序进行分析。图像的像素格式为8BppIndexed。
当我将这个图像导入C#并绘制它的直方图时,我只看到16个灰度值,如下所示:
这些峰值之间的所有值均为0.
这是正常的直方图应该是这样的(不要介意颜色,这个直方图是用另一个工具制作的):
第一个直方图(int [])由以下代码组成:
public static int[] GetHistogram(Bitmap b)
{
int[] myHistogram = new int[256];
for (int i = 0; i < myHistogram.Length; i++)
myHistogram[i] = 0;
BitmapData bmData = null;
try
{
//Lock it fixed with 32bpp
bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int scanline = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte* p = (byte*)(void*)Scan0;
int nWidth = b.Width;
int nHeight = b.Height;
for (int y = 0; y < nHeight; y++)
{
for (int x = 0; x < nWidth; x++)
{
long Temp = 0;
Temp += p[0]; // p[0] - blue, p[1] - green , p[2]-red
Temp += p[1];
Temp += p[2];
Temp = (int)Temp / 3;
myHistogram[Temp]++;
//we do not need to use any offset, we always can increment by pixelsize when
//locking in 32bppArgb - mode
p += 4;
}
}
}
b.UnlockBits(bmData);
}
catch
{
try
{
b.UnlockBits(bmData);
}
catch
{
}
}
return myHistogram;
}
为了确保此代码不是问题,我尝试使用AForge.Math.Histogram方式甚至for-in-for循环迭代所有像素。每次我得到相同的结果。
现在这里是有趣的部分:
这些要点告诉我,将图像导入代码的方式可能有问题,所以我尝试了不同的方法来导入图像:
Bitmap bmp = (Bitmap)Bitmap.FromFile(path);
或
Bitmap bmp = AForge.Imaging.Image.FromFile(path);
或
Stream imageStreamSource = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
System.Windows.Media.Imaging.JpegBitmapDecoder decoder = new System.Windows.Media.Imaging.JpegBitmapDecoder(imageStreamSource, System.Windows.Media.Imaging.BitmapCreateOptions.PreservePixelFormat, System.Windows.Media.Imaging.BitmapCacheOption.Default);
System.Windows.Media.Imaging.BitmapSource bitmapSource = decoder.Frames[0];
System.Windows.Controls.Image image = new System.Windows.Controls.Image();
image.Source = bitmapSource;
image.Stretch = System.Windows.Media.Stretch.None;
MemoryStream ms = new MemoryStream();
var encoder = new System.Windows.Media.Imaging.BmpBitmapEncoder();
encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(image.Source as System.Windows.Media.Imaging.BitmapSource));
encoder.Save(ms);
ms.Flush();
System.Drawing.Image myImage = System.Drawing.Image.FromStream(ms);
Bitmap bmp = (Bitmap)Bitmap.FromStream(ms);
其中没有一个给出与仅有16个结果的直方图不同的直方图。
我不能在我的扫描仪中使用.bmp扩展名,因为我需要制作大量的图像,一个.bmp图像大约200mb(是的,图像需要高分辨率),而.jpg只是30MB。此外,我已经制作了许多无法重新制作的.jpg图像,因为已扫描的对象不再存在。
注意:我知道使用.jpg扩展程序是压缩图像的有效方法。这不是当前的问题。
这是使用与第一个完全相同的代码创建的直方图,与我计算机上的另一个随机.jpg图像一样:
这听起来对任何人都很熟悉吗?我觉得我已经尝试了一切。还有另一种方法可以解决我尚未找到的问题吗?
修改
我以为我找到了一种非常脏的方法来解决我的问题,但确实改变了直方图:
Bitmap temp = (Bitmap)Bitmap.FromFile(m_sourceImageFileName);
if (temp.PixelFormat == PixelFormat.Format8bppIndexed ||
temp.PixelFormat == PixelFormat.Format4bppIndexed ||
temp.PixelFormat == PixelFormat.Format1bppIndexed ||
temp.PixelFormat == PixelFormat.Indexed)
{
//Change pixelformat to a format that AForge can work with
Bitmap tmp = temp.Clone(new Rectangle(0, 0, temp.Width, temp.Height), PixelFormat.Format24bppRgb);
//This is a super dirty way to make sure the histogram shows more than 16 grey values.
for (int i = 0; true; i++)
{
if (!File.Exists(m_sourceImageFileName + i + ".jpg"))
{
tmp.Save(m_sourceImageFileName + i + ".jpg");
tmp.Dispose();
temp = AForge.Imaging.Image.FromFile(m_sourceImageFileName + i + ".jpg");
File.Delete(m_sourceImageFileName + i + ".jpg");
break;
}
}
}
Bitmap properImage = temp;
这是新的直方图:
正如您所看到的,它与直方图应该是什么样子不一样。 我发现问题可能是因为图像是8bppIndexed jpeg图像,而jpeg只支持24bppRgb图像。任何解决方案?
答案 0 :(得分:1)
我认为线索属于&#34;索引&#34;在你的第二行。查找表中可能只有16种颜色。您可以发布原始扫描图像,以便我们可以查看其中是否有更多阴影?如果没有,请尝试使用ImageMagick计算颜色
像这样得到直方图:
convert yourimage.jpg -format %c histogram:info:-
convert yourimage.jpg -colorspace rgb -colors 256 -depth 8 -format "%c" histogram:info:
或者计算这样的独特颜色:
identify -verbose yourimage.jpg | grep -i colors:
或者像这样转储所有像素:
convert yourimage.jpg -colorspace rgb -colors 256 -depth 8 txt:
答案 1 :(得分:0)
好吧,我通过打开JPEG并用java中的ImageJ库将其保存为bmp来解决它。我从代码中创建了一个.jar文件,并使用此代码将bmp放入我的c#代码中:
string extension = m_sourceImageFileName.Substring(m_sourceImageFileName.LastIndexOf("."), m_sourceImageFileName.Length - m_sourceImageFileName.LastIndexOf("."));
int exitcode;
ProcessStartInfo ProcessInfo;
Process process;
ProcessInfo = new ProcessStartInfo("java.exe", @"-jar ""C:\Users\stevenh\Documents\Visual Studio 2010\Projects\BlackSpotDetection V2.0\ConvertToBmp\dist\ConvertToBmp.jar"" " + extension + " " + m_sourceImageFileName + " " + m_addedImageName);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = false;
// redirecting standard output and error
ProcessInfo.RedirectStandardError = true;
ProcessInfo.RedirectStandardOutput = true;
process = Process.Start(ProcessInfo);
process.WaitForExit();
//Reading output and error
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
exitcode = process.ExitCode;
if (exitcode != 0)
{
statusLabel.Text = output;
MessageBox.Show("Error in external process: converting image to bmp.\n" + error);
//Exit code '0' denotes success and '1' denotes failure
return;
}
else
statusLabel.Text = "Awesomeness";
process.Close();
Bitmap realImage = AForge.Imaging.Image.FromFile(m_addedImageName);
File.Delete(m_addedImageName);
jar将接收扩展名m_sourceImageFileName和m_addedImageFileName。它将打开sourceImage并以m_addedImageFileName的名称保存它 我正在使用AForge库来打开图像,因为这个库在打开时不会锁定图像,这使我能够删除“自制”图像。