我正在尝试将RGB图像转换为灰度图像。 RGB图像为160 * 120 * 4,而我的灰度为160 * 120 * 1。然而,它并没有让我觉得我只是简单的黑色,它需要很长时间。这是我写的wat,请指教。感谢
int i, j, sum;
Image = new unsigned char [ 160 * 120 * 1 ];
for( int j = 0; j < 120; j++ ) {
for( int i = 0; i < 160; i++ ) {
sum=0;
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
*Image = sum/4;
PaintBox2->Canvas->Pixels[ i ][ j ] = *Image;
Image++;
}
}
答案 0 :(得分:1)
我可以立即看到代码中的几个问题。最引人注目的是来自最里面的for循环:
sum=0;
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
*Image = sum/4;
在这里,您只需将相同的值添加到sum
四次,然后再除以四。这使得这六行等同于
*Image = PaintBox1->Canvas->Pixels[ i ][ j ];
显然,你实际上想要平均每个频道。如果您的RGB图像是作为三维数组实现的,那么这可能类似于:
sum = 0;
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 0 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 1 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 2 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 3 ];
*Image = sum/4;
但是,从您的代码示例中,看起来您的RGB图像实际上是作为(un)有符号整数的二维数组实现的。在这种情况下,以下代码应该足够(假设整数是您机器上的四个字节):
sum = 0;
unsigned int pixel = PaintBox1->Canvas->Pixels[ i ][ j ];
for(int k = 0; k < 4; ++k)
{
sum += pixel & 0xFF;
pixel >>= 1;
}
*Image = sum/4;
我看到的另一个主要问题是你没有保持指向灰度数组开头的指针。您将其初始化为
Image = new unsigned char[ 160 * 120 * 1 ];
这很好。但是每次循环,你都写了
Image++;
相反,你应该保持一个指向数组开头的指针,并有一个临时指针作为迭代器:
// before the for loops
Image = new unsigned char[ 160 * 120 * 1 ];
unsigned char * temp = Image;
// at the end of the inner for loop:
temp++;
所以你只能移动temp
指针,而Image
保持不变。
答案 1 :(得分:0)
VCL 画布使用TColor
保留颜色。但是,内部格式由PixelFormat
的{{1}}格式定义。通常为Canvas
或pf32bit
... pf24bit
始终为32位无论使用哪种图像TColor
,因为转换过程中都会发生很多转换(这就是为什么它这么慢),但是请注意,不同的PixelFormat
设置可能会颠倒RGB顺序,从而使{{1} }也颠倒了(渲染为PixelFormat
)!!!
例如,如果您使用 VCL s
clYellow,...
则每个像素为32位值。您可以为位图安全地执行此操作,但是我不确定Form / PaintBox画布是否与窗口绑定在一起,我怀疑您的clAqua,...
是相似的(很可能是24位),因此您需要稍微更改代码:
Graphics::TBitmap *bmp=new Graphics::TBitmap;
bmp->PixelFormat=pf32bit;
PixelFormat
属性是sloooow我将使用VCL位图,而使用其int x,y,xs=160,ys=120;
DWORD rgb,bw;
Image = new unsigned char [ xs*ys*1 ];
for(y=0;y<ys;y++)
for(x=0;x<xs;x++)
{
rgb = PaintBox1->Canvas->Pixels[x][y];
bw = ( rgb &255) // sum r,g,b
+((rgb>> 8)&255)
+((rgb>>16)&255);
bw/=3; // normalize
*Image = bw; // write to your array
Image++;
bw*=0x00010101; // convert intensity to grayscale RGB color (you can shift and or instead)
PaintBox2->Canvas->Pixels[x][y]=TColor(bw); // write back
} Image-=xs*ys;
属性,它的速度快约1000倍以上,并且实现了加载/保存功能,因此您可以使用bmp文件容易。有关更多信息,请参见:
还有更多将RGB转换为强度的方法,请参见: