如何从System.Drawing.Bitmap转换为灰度,然后转换为双精度数组(Double [,]),然后再转换为灰度位图? [英] How to convert from System.Drawing.Bitmap to grayscale, then to array of doubles (Double[,]), then back to grayscale Bitmap?
问题描述
我需要在照片中执行一些数学运算,为此我需要图像的浮点灰度版本(可能来自JPG,PNG或具有各种颜色深度的BMP文件)。
I need to perform some mathematical operations in photographs, and for that I need the floating point grayscale version of an image (which might come from JPG, PNG or BMP files with various colordepths).
我以前在Python中使用 PIL
和 scipy.ndimage
来做到这一点,它是非常简单地用 PIL
转换为灰度,然后转换为带有 numpy
的浮点数数组,但现在我需要在C#中做类似的事情,我很困惑如何这样做。
I used to do that in Python using PIL
and scipy.ndimage
, and it was very straightforward to convert to grayscale with PIL
and then to an array of floating-point numbers with numpy
, but now I need to do something similar in C#, and I'm confused how to do so.
我读过这个非常好的教程,这似乎是一个反复出现的参考,但只涵盖了转换为灰度部分,我不知道如何从Bitmap获取双打数组,然后(在某个时刻)将其转换回System.Drawing.Bitmap以供查看。
I have read this very nice tutorial, that seems to be a recurring reference, but that only covers the "convert to grayscale" part, I am not sure how to get an array of doubles from a Bitmap, and then (at some moment) to convert it back to System.Drawing.Bitmap for viewing.
推荐答案
决赛代码,主要基于从评论中提取的提示,特别是 LockBits
部分(这里的博客文章)以及R,G和B值之间的感知平衡(这里不是最重要的,但需要了解的事情):
The final code, based mostly in tips taken from the comments, specifically the LockBits
part (blog post here) and the perceptual balancing between R, G and B values (not paramount here, but something to know about):
private double[,] TransformaImagemEmArray(System.Drawing.Bitmap imagem) {
// Transforma a imagem de entrada em um array de doubles
// com os valores grayscale da imagem
BitmapData bitmap_data = imagem.LockBits(new System.Drawing.Rectangle(0,0,_foto_franjas_original.Width,_foto_franjas_original.Height),
ImageLockMode.ReadOnly, _foto_franjas_original.PixelFormat);
int pixelsize = System.Drawing.Image.GetPixelFormatSize(bitmap_data.PixelFormat)/8;
IntPtr pointer = bitmap_data.Scan0;
int nbytes = bitmap_data.Height * bitmap_data.Stride;
byte[] imagebytes = new byte[nbytes];
System.Runtime.InteropServices.Marshal.Copy(pointer, imagebytes, 0, nbytes);
double red;
double green;
double blue;
double gray;
var _grayscale_array = new Double[bitmap_data.Height, bitmap_data.Width];
if (pixelsize >= 3 ) {
for (int I = 0; I < bitmap_data.Height; I++) {
for (int J = 0; J < bitmap_data.Width; J++ ) {
int position = (I * bitmap_data.Stride) + (J * pixelsize);
blue = imagebytes[position];
green = imagebytes[position + 1];
red = imagebytes[position + 2];
gray = 0.299 * red + 0.587 * green + 0.114 * blue;
_grayscale_array[I,J] = gray;
}
}
}
_foto_franjas_original.UnlockBits(bitmap_data);
return _grayscale_array;
}
这篇关于如何从System.Drawing.Bitmap转换为灰度,然后转换为双精度数组(Double [,]),然后再转换为灰度位图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!