制作马赛克图像(位图格式)



我想制作一张不同窗口大小的马赛克照片(由用户决定(。这就像是代码的初稿,但我在获取像素和计算平均值方面遇到了问题。然后将平均值放在每个像素中,并继续到最后。甚至我在转换不同类型的图像时也会出错:(其他部件制造商也会提供灰度图像(很抱歉,我还处于学习图像处理的第一步。

''' void CImageProcessingDoc::OnProcessMosaic()
{
if (m_pImage) {
DlgMosaicOption dlg;
if (dlg.DoModal() == IDOK) {
DWORD dwWindowSize = dlg.m_dwWindowSize;
DWORD width = m_pImage->GetWidth();
DWORD height = m_pImage->GetHeight();
RGBQUAD color;
RGBQUAD newcolor;
float X_step = width / dwWindowSize;
float Y_step = height / dwWindowSize;
int avg, pixel;
for (DWORD y = 0; y < dwWindowSize; y++) {
for (DWORD x = 0; x < dwWindowSize; x++) {
color = m_pImage->GetPixelColor(x, y);
(RGBQUAD) pixel =  m_pImage->GetPixelColor(x, y);
avR += (int)(color.red(pixel);
avG += (int)(color.green(pixel);
avB += (int)(color.blue(pixel);
newcolor.rgbBlue  = (BYTE)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
newcolor.rgbGreen = (BYTE)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
newcolor.rgbRed   = (BYTE)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
m_pImage->SetPixelColor(x, y, newcolor);
}
}
}
}
} '''

有人能帮我理解一下这个问题吗?

我认为您在这里混淆了空间、光谱和时间平均值。

空间平均值

这是计算一个区域上像素的平均值的操作。

您必须计算eR = 1/N * (P0.R + P1.R + P2.R + P3.R + ...)eG = 1/N * (P0.G + P1.G + ...)eB = 1/N * (P0.B + P1.B + ...)

你会得到一个像素,它的颜色和输入图片中的颜色一样多,但空间频率有限,这样计算的图片会显得模糊,没有细节

光谱平均值

这是计算每个像素的分量(光谱(的平均值的操作。

你必须计算e = 1/3 * (P0.R + P0.G + P0.B)

你会得到一张单色照片,其空间频率与初始照片完全相同。

时间平均值

虽然你还没有谈到它,但这是供参考的。这个想法是计算时间序列中N张图片的每个像素和每个分量的平均值

这会产生一种运动模糊的画面。

答案

如果我正确理解你的问题,你希望光谱平均值将RGB转换为grey = (R+G+B)/3的平均灰度值。

因此,像素循环应该是这样的:

for (DWORD y = 0; y < dwWindowSize; y++) {
for (DWORD x = 0; x < dwWindowSize; x++) {
color = m_pImage->GetPixelColor(x, y);
float avg = (color.rgbRed + color.rgbGreen + color.rgbBlue) / 3.f;
m_pImage->SetPixelColor(x, y, RGBQUAD(avg, avg, avg, 1.0f));
}
}

请注意,使用平均值将非线性RGB(通常称为sRGB(转换为亮度是RGB到灰度转换的糟糕公式。您应该阅读RGB到Lab*的转换(您只对L部分感兴趣(,或者至少阅读RGB到YUV的转换(仅对Y部分感兴趣。

如果您的问题是调整输入图片的大小,那么您没有使用适当的算法,您想要的是重新采样