2012-09-20 21 views
1

这使我困惑了两个小时。读取图像文件会导致Matlab中的imread与C#中的Image.FromFile之间的像素值不同?为什么图像的像素值在读取方法上有所不同?

aa=imread('myfile.tif') 

max(aa(:)) = 248 in matlab 

在C#

var image2Array = imageToByteArray((Bitmap) Image.FromFile("myfile.tif")); 
byte maxx = 0; 
foreach(var a in image2Array) 
{ 
    maxx = Math.Max(maxx, a); 
} 
//maxx = 255 

Futhermore,在Matlab,

aa(1,1) = 13, 
aa(1,2) = 13 

但在C#

image2Array[0]=17, 
image2Array[1]=0 

他们应该是相同的。

顺便说一下,在这种情况下,像素类型是uint8。所以没有尺寸差异。

如果你问我如何从Image获得字节数组,我使用MSDN document来制作这种方法。

public byte[] imageToByteArray(Bitmap bmp) 
    { 
     // Lock the bitmap's bits. 
     Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 
     BitmapData bmpData = bmp.LockBits(
      rect, 
      ImageLockMode.ReadWrite, 
      bmp.PixelFormat); 

     // Get the address of the first line. 
     IntPtr ptr = bmpData.Scan0; 

     // Declare an array to hold the bytes of the bitmap. 
     int bytes = Math.Abs(bmpData.Stride)*bmp.Height; 
     byte[] rgbValues = new byte[bytes]; 

     // Copy the RGB values into the array. 
     System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); 
     // Unlock the bits. 
     bmp.UnlockBits(bmpData); 
     return rgbValues; 
    } 

我在这里做错了什么?我怀疑他们使用不同的阅读算法,因为两个结果图像看起来相同。

UPDATE:

我不认为有什么不对我在做什么。我的结论是,读取tif作为位图是问题的原因。确认这个理论,

  1. 我显示了两个图像,他们看起来完全一样。所以我认为我没有犯错。

  2. 我试着用opencv读取同一个文件,其像素值与matlab中的完全一样。这对我来说令人惊讶。我从现在开始非常谨慎地在C#中使用Bitmap。

回答

1

TIFF有很多格式,您试图将其作为位图读取。

我建议使用专有的TIFF阅读器来阅读它:Good Tiff library for .NET

+0

是的,我正在尝试使用OpenCV。感谢您的确认。 –

+0

我能用matlab复制imread与OpenCV的图像。所以我认为将它作为位图阅读并不是一个好主意,这对我来说是令人惊讶的。 –

5

imageToByteArray方法确实返回一个字节数组,但你不能假定每个字节是一个像素。 PixelFormat决定像素数据如何存储在字节数组中。

我见过的最好的网站是http://www.bobpowell.net/lockingbits.htm,但是 它看起来并不像现在这样的网站,所以here's the Google cache version

编辑:

如果是的PixelFormat Format8bppIndexed,那么这(未经测试)的代码应该给你的每个像素的颜色值。

var bmp = (Bitmap)Bitmap.FromFile("myfile.tif"); 

// ******* Begin copying your imageToByteArray method 
// Lock the bitmap's bits. 
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 
BitmapData bmpData = bmp.LockBits(
    rect, 
    ImageLockMode.ReadWrite, 
    bmp.PixelFormat); 

// Get the address of the first line. 
IntPtr ptr = bmpData.Scan0; 

// Declare an array to hold the bytes of the bitmap. 
int bytes = Math.Abs(bmpData.Stride) * bmp.Height; 
byte[] imageData = new byte[bytes]; 

// Copy the RGB values into the array. 
System.Runtime.InteropServices.Marshal.Copy(ptr, imageData, 0, bytes); 
// Unlock the bits. 
bmp.UnlockBits(bmpData); 
// ******* End copying your imageToByteArray method 

// Now loop through each pixel... The byte array contains extra bytes 
// used for padding so we can't just loop through every byte in the array. 
// This is done by using the Stride property on bmpData. 
for (int y = 0; y < bmpData.Height; y++) 
{ 
    for (int x = 0; x < bmpData.Width; x++) 
    { 
     var offset = (y * bmpData.Stride) + x; 

     // The byte in the image array gives the offset into the palette 
     var paletteIndex = imageData[offset]; 

     // Given the offset, find the matching color in the palette 
     var color = bmp.Palette.Entries[offset]; 

     // Look at the color value here... 
    } 
} 
+0

+1对此。作为快速的试金石测试,检查字节数组中元素的数量与Matlab报告的图像大小。我冒昧猜测它更大。 – peakxu

+0

我想我明白这一点。但是这种情况下的tif文件是uint8,与byte或unsigned char相同。 –

+0

@peakxu我已经查过。两者之间的元素数量是相同的。 –

相关问题