灰度图像的图像乘法
Image Multiplication of Gray Image
当我处理 2 个灰度图像的图像乘法时,我确实看到了颜色分量。无法弄清楚这里到底出了什么问题:
图片:
反射图像:
以上图像的图像乘法:
这是我的图像乘法函数:
public Bitmap MaskImage(Bitmap SrcBitmap1, Bitmap SrcBitmap2)
{
int width;
int height;
//Message = "Impossible.";
if (SrcBitmap1.Width < SrcBitmap2.Width)
width = SrcBitmap1.Width;
else
width = SrcBitmap2.Width;
if (SrcBitmap1.Height < SrcBitmap2.Height)
height = SrcBitmap1.Height;
else
height = SrcBitmap2.Height;
Bitmap bitmap = new Bitmap(width, height);
int clr1, clr2;
try
{
BitmapData Src1Data = SrcBitmap1.LockBits(new Rectangle(0, 0, SrcBitmap1.Width, SrcBitmap1.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData Src2Data = SrcBitmap2.LockBits(new Rectangle(0, 0, SrcBitmap2.Width, SrcBitmap2.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData DestData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe
{
//Following is list of offset for different bit images
//8 bit : 1
//16 bit : 2
//24 bit : 3 and
//32 bit : 4
int xOffset = 1;
for (int col = 0; col < bitmap.Height - 1; col++)
{
byte* Src1Ptr = (byte*)Src1Data.Scan0 + col * Src1Data.Stride;
byte* Src2Ptr = (byte*)Src2Data.Scan0 + col * Src2Data.Stride;
byte* DestPtr = (byte*)DestData.Scan0 + col * DestData.Stride;
for (int row = 0; row < bitmap.Width - 1; row++)
{
clr1 = (Src1Ptr[row * xOffset] + Src1Ptr[row * xOffset + 1] + Src1Ptr[row * xOffset + 2]) / 3;
clr2 = (Src2Ptr[row * xOffset] + Src2Ptr[row * xOffset + 1] + Src2Ptr[row * xOffset + 2]) / 3;
clr1 *= clr2;
if (clr1 == 0)
{
DestPtr[row * xOffset] = (byte)(0);
DestPtr[row * xOffset + 1] = (byte)(0);
DestPtr[row * xOffset + 2] = (byte)(0);
}
else
{
DestPtr[row * xOffset] = (byte)(Src2Ptr[row * xOffset]);
DestPtr[row * xOffset + 1] = (byte)(Src2Ptr[row * xOffset + 1]);
DestPtr[row * xOffset + 2] = (byte)(Src2Ptr[row * xOffset + 2]);
}
}
}
}
bitmap.UnlockBits(DestData);
SrcBitmap1.UnlockBits(Src1Data);
SrcBitmap2.UnlockBits(Src2Data);
SrcBitmap1.Dispose();
SrcBitmap2.Dispose();
}
catch (Exception ex)
{
Console.Write(ex);
}
return bitmap;
}
编辑:
基于 Spektre 代码:
问题好像还是一样。虽然我尝试使用强度值而不仅仅是颜色通道:下面是代码的变化:无法真正弄清楚这里发生了什么。
输出:
public Bitmap MaskImage(Bitmap SrcBitmap1, Bitmap SrcBitmap2)
{
int width;
int height;
//Message = "Impossible.";
if (SrcBitmap1.Width < SrcBitmap2.Width)
width = SrcBitmap1.Width;
else
width = SrcBitmap2.Width;
if (SrcBitmap1.Height < SrcBitmap2.Height)
height = SrcBitmap1.Height;
else
height = SrcBitmap2.Height;
Bitmap bitmap = new Bitmap(width, height);
try
{
BitmapData Src1Data = SrcBitmap1.LockBits(new Rectangle(0, 0, SrcBitmap1.Width, SrcBitmap1.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData Src2Data = SrcBitmap2.LockBits(new Rectangle(0, 0, SrcBitmap2.Width, SrcBitmap2.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData DestData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe
{
//Following is list of offset for different bit images
//8 bit : 1
//16 bit : 2
//24 bit : 3 and
//32 bit : 4
int xOffset = 1;
for (int col = 0; col < bitmap.Height - 1; col++)
{
byte* Src1Ptr = (byte*)Src1Data.Scan0 + col * Src1Data.Stride;
byte* Src2Ptr = (byte*)Src2Data.Scan0 + col * Src2Data.Stride;
byte* DestPtr = (byte*)DestData.Scan0 + col * DestData.Stride;
for (int row = 0; row < bitmap.Width - 1; row++)
{
byte i1 = Src1Ptr[row * xOffset];
bbyte i2 = Src2Ptr[row * xOffset];
DestPtr[row * xOffset + 0] = (byte)((((ushort)(i1) * (ushort)(i2)) >> 8));
DestPtr[row * xOffset + 1] = (byte)((ushort)(((ushort)(i1) * (ushort)(i2)) >> 8));
DestPtr[row * xOffset + 2] = (byte)((ushort)(((ushort)(i1) * (ushort)(i2)) >> 8));
}
}
}
bitmap.UnlockBits(DestData);
SrcBitmap1.UnlockBits(Src1Data);
SrcBitmap2.UnlockBits(Src2Data);
SrcBitmap1.Dispose();
SrcBitmap2.Dispose();
}
catch (Exception ex)
{
Console.Write(ex);
}
return bitmap;
}
关于您的代码的一些注释:
您的图像格式已经是 8bpp,所以这里没有 RGB 通道:
clr1 = (Src1Ptr[row * xOffset] + Src1Ptr[row * xOffset + 1] + Src1Ptr[row * xOffset + 2]) / 3;
clr2 = (Src2Ptr[row * xOffset] + Src2Ptr[row * xOffset + 1] + Src2Ptr[row * xOffset + 2]) / 3;
所以这里不需要+1和+2,除以3让图像变灰。因为输入的图片已经是灰度图了。
此外,当将值分配回目标图像时,这应该就足够了:
DestPtr[row * xOffset] = (byte) //value of multiplied gray level
在您的示例中,您只是将第二张图片的值赋值回来。
生成的图像为什么有颜色与移位(偏移、+1 和 +2)有关,因为图像未正确写入。
Joel Legaspi Enriquez 是对的我只想补充
- 你需要乘以强度而不是颜色
- RGB 中编码为颜色的灰度是
R==G==B
- 这就是为什么你只需要一个组件
- 乘以
rgb1*rgb2
得到 (3*8 + 3*8 bit result)
- 这是一个很大的数字,RGB 通道之间有很多溢出
- 这就是颜色不知从何而来的原因
补救措施:
仅乘以强度
- 所以单频道并不重要
r,g,b
将输出范围标准化回原始位计数
- 所以每个通道通常是8位
- 相乘后是16位
- 所以只需除以 (1^8) 即 256 或右移 8 位
然后将结果复制到所有通道
BYTE i1=Src1Ptr[row * xOffset];
BYTE i2=Src2Ptr[row * xOffset];
DestPtr[row * xOffset+0] = BYTE(WORD((WORD(i1)*WORD(i2))>>8));
DestPtr[row * xOffset+1] = BYTE(WORD((WORD(i1)*WORD(i2))>>8));
DestPtr[row * xOffset+2] = BYTE(WORD((WORD(i1)*WORD(i2))>>8));
[edit1]
你的地址计算看起来很可疑
- 我以为它被封装在
xOffset
中,没有进一步查看
- 但再看一眼,你将 ti 设置为 1 并且你没有在我能看到的任何地方应用 y 偏移量
- 我会像
address = (x*Stride)+(y*Width*stride)
那样计算像素 (x,y) 的地址
- 可能是我看错了你的代码,但它看起来像
- 您还混合了
col
和 row
- 位图存储为行(行)而不是列
- 所以
for
应该交换
- 外循环应该是
y
(行)和内循环x
(列)
当我处理 2 个灰度图像的图像乘法时,我确实看到了颜色分量。无法弄清楚这里到底出了什么问题:
图片:
这是我的图像乘法函数:
public Bitmap MaskImage(Bitmap SrcBitmap1, Bitmap SrcBitmap2)
{
int width;
int height;
//Message = "Impossible.";
if (SrcBitmap1.Width < SrcBitmap2.Width)
width = SrcBitmap1.Width;
else
width = SrcBitmap2.Width;
if (SrcBitmap1.Height < SrcBitmap2.Height)
height = SrcBitmap1.Height;
else
height = SrcBitmap2.Height;
Bitmap bitmap = new Bitmap(width, height);
int clr1, clr2;
try
{
BitmapData Src1Data = SrcBitmap1.LockBits(new Rectangle(0, 0, SrcBitmap1.Width, SrcBitmap1.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData Src2Data = SrcBitmap2.LockBits(new Rectangle(0, 0, SrcBitmap2.Width, SrcBitmap2.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData DestData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe
{
//Following is list of offset for different bit images
//8 bit : 1
//16 bit : 2
//24 bit : 3 and
//32 bit : 4
int xOffset = 1;
for (int col = 0; col < bitmap.Height - 1; col++)
{
byte* Src1Ptr = (byte*)Src1Data.Scan0 + col * Src1Data.Stride;
byte* Src2Ptr = (byte*)Src2Data.Scan0 + col * Src2Data.Stride;
byte* DestPtr = (byte*)DestData.Scan0 + col * DestData.Stride;
for (int row = 0; row < bitmap.Width - 1; row++)
{
clr1 = (Src1Ptr[row * xOffset] + Src1Ptr[row * xOffset + 1] + Src1Ptr[row * xOffset + 2]) / 3;
clr2 = (Src2Ptr[row * xOffset] + Src2Ptr[row * xOffset + 1] + Src2Ptr[row * xOffset + 2]) / 3;
clr1 *= clr2;
if (clr1 == 0)
{
DestPtr[row * xOffset] = (byte)(0);
DestPtr[row * xOffset + 1] = (byte)(0);
DestPtr[row * xOffset + 2] = (byte)(0);
}
else
{
DestPtr[row * xOffset] = (byte)(Src2Ptr[row * xOffset]);
DestPtr[row * xOffset + 1] = (byte)(Src2Ptr[row * xOffset + 1]);
DestPtr[row * xOffset + 2] = (byte)(Src2Ptr[row * xOffset + 2]);
}
}
}
}
bitmap.UnlockBits(DestData);
SrcBitmap1.UnlockBits(Src1Data);
SrcBitmap2.UnlockBits(Src2Data);
SrcBitmap1.Dispose();
SrcBitmap2.Dispose();
}
catch (Exception ex)
{
Console.Write(ex);
}
return bitmap;
}
编辑:
基于 Spektre 代码:
问题好像还是一样。虽然我尝试使用强度值而不仅仅是颜色通道:下面是代码的变化:无法真正弄清楚这里发生了什么。
输出:
public Bitmap MaskImage(Bitmap SrcBitmap1, Bitmap SrcBitmap2)
{
int width;
int height;
//Message = "Impossible.";
if (SrcBitmap1.Width < SrcBitmap2.Width)
width = SrcBitmap1.Width;
else
width = SrcBitmap2.Width;
if (SrcBitmap1.Height < SrcBitmap2.Height)
height = SrcBitmap1.Height;
else
height = SrcBitmap2.Height;
Bitmap bitmap = new Bitmap(width, height);
try
{
BitmapData Src1Data = SrcBitmap1.LockBits(new Rectangle(0, 0, SrcBitmap1.Width, SrcBitmap1.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData Src2Data = SrcBitmap2.LockBits(new Rectangle(0, 0, SrcBitmap2.Width, SrcBitmap2.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
BitmapData DestData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe
{
//Following is list of offset for different bit images
//8 bit : 1
//16 bit : 2
//24 bit : 3 and
//32 bit : 4
int xOffset = 1;
for (int col = 0; col < bitmap.Height - 1; col++)
{
byte* Src1Ptr = (byte*)Src1Data.Scan0 + col * Src1Data.Stride;
byte* Src2Ptr = (byte*)Src2Data.Scan0 + col * Src2Data.Stride;
byte* DestPtr = (byte*)DestData.Scan0 + col * DestData.Stride;
for (int row = 0; row < bitmap.Width - 1; row++)
{
byte i1 = Src1Ptr[row * xOffset];
bbyte i2 = Src2Ptr[row * xOffset];
DestPtr[row * xOffset + 0] = (byte)((((ushort)(i1) * (ushort)(i2)) >> 8));
DestPtr[row * xOffset + 1] = (byte)((ushort)(((ushort)(i1) * (ushort)(i2)) >> 8));
DestPtr[row * xOffset + 2] = (byte)((ushort)(((ushort)(i1) * (ushort)(i2)) >> 8));
}
}
}
bitmap.UnlockBits(DestData);
SrcBitmap1.UnlockBits(Src1Data);
SrcBitmap2.UnlockBits(Src2Data);
SrcBitmap1.Dispose();
SrcBitmap2.Dispose();
}
catch (Exception ex)
{
Console.Write(ex);
}
return bitmap;
}
关于您的代码的一些注释:
您的图像格式已经是 8bpp,所以这里没有 RGB 通道:
clr1 = (Src1Ptr[row * xOffset] + Src1Ptr[row * xOffset + 1] + Src1Ptr[row * xOffset + 2]) / 3;
clr2 = (Src2Ptr[row * xOffset] + Src2Ptr[row * xOffset + 1] + Src2Ptr[row * xOffset + 2]) / 3;
所以这里不需要+1和+2,除以3让图像变灰。因为输入的图片已经是灰度图了。
此外,当将值分配回目标图像时,这应该就足够了:
DestPtr[row * xOffset] = (byte) //value of multiplied gray level
在您的示例中,您只是将第二张图片的值赋值回来。
生成的图像为什么有颜色与移位(偏移、+1 和 +2)有关,因为图像未正确写入。
Joel Legaspi Enriquez 是对的我只想补充
- 你需要乘以强度而不是颜色
- RGB 中编码为颜色的灰度是
R==G==B
- 这就是为什么你只需要一个组件
- 乘以
rgb1*rgb2
得到(3*8 + 3*8 bit result)
- 这是一个很大的数字,RGB 通道之间有很多溢出
- 这就是颜色不知从何而来的原因
补救措施:
仅乘以强度
- 所以单频道并不重要
r,g,b
- 所以单频道并不重要
将输出范围标准化回原始位计数
- 所以每个通道通常是8位
- 相乘后是16位
- 所以只需除以 (1^8) 即 256 或右移 8 位
然后将结果复制到所有通道
BYTE i1=Src1Ptr[row * xOffset]; BYTE i2=Src2Ptr[row * xOffset]; DestPtr[row * xOffset+0] = BYTE(WORD((WORD(i1)*WORD(i2))>>8)); DestPtr[row * xOffset+1] = BYTE(WORD((WORD(i1)*WORD(i2))>>8)); DestPtr[row * xOffset+2] = BYTE(WORD((WORD(i1)*WORD(i2))>>8));
[edit1]
你的地址计算看起来很可疑
- 我以为它被封装在
xOffset
中,没有进一步查看 - 但再看一眼,你将 ti 设置为 1 并且你没有在我能看到的任何地方应用 y 偏移量
- 我会像
address = (x*Stride)+(y*Width*stride)
那样计算像素 (x,y) 的地址
- 可能是我看错了你的代码,但它看起来像
- 您还混合了
col
和row
- 位图存储为行(行)而不是列
- 所以
for
应该交换 - 外循环应该是
y
(行)和内循环x
(列)