Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ (C+;+;)(Visual Studio)将RGB更改为灰度_C++_Image Processing - Fatal编程技术网

C++ (C+;+;)(Visual Studio)将RGB更改为灰度

C++ (C+;+;)(Visual Studio)将RGB更改为灰度,c++,image-processing,C++,Image Processing,我正在访问图像,如下所示: pDoc = GetDocument(); int iBitPerPixel = pDoc->_bmp->bitsperpixel; // used to see if grayscale(8 bits) or RGB (24 bits) int iWidth = pDoc->_bmp->width; int iHeight = pDoc->_bmp->height; BYTE *pImg = pDoc->_bmp-&

我正在访问图像,如下所示:

pDoc = GetDocument();

int iBitPerPixel = pDoc->_bmp->bitsperpixel;    // used to see if grayscale(8 bits) or RGB (24 bits)
int iWidth = pDoc->_bmp->width;
int iHeight = pDoc->_bmp->height;
BYTE *pImg = pDoc->_bmp->point;     // pointer used to point at pixels in the image
int Wp = iWidth;
const int area = iWidth * iHeight;
int r;          // red pixel value
int g;          // green pixel value
int b;          // blue pixel value
int gray;       // gray pixel value

BYTE *pImgGS = pImg;                    // grayscale image pixel array
并尝试将rgb图像更改为灰色,如下所示:

    // convert RGB values to grayscale at each pixel, then put in grayscale array
    for (int i = 0; i<iHeight; i++)
        for (int j = 0; j<iWidth; j++)
        {
            r = pImg[i*iWidth * 3 + j * 3 + 2];
            g = pImg[i*iWidth * 3 + j * 3 + 1];
            b = pImg[i*Wp + j * 3];

            r * 0.299;
            g * 0.587;
            b * 0.144;

            gray = std::round(r + g + b);

            pImgGS[i*Wp + j] = gray;
        }
//在每个像素处将RGB值转换为灰度,然后放入灰度数组中

对于(int i=0;i首先检查图像类型是否为每像素24位。 第二,为PIMG分配内存

BYTE* pImgGS = (BTYE*)malloc(sizeof(BYTE)*iWidth *iHeight); 
请参阅文章,了解bmp数据是如何保存的。bmp图像是颠倒保存的。另外,信息的前54字节是BITMAPFILEHEADER。 因此,您应该按照以下方式访问值:

double r,g,b;
unsigned char gray;
for (int i = 0; i<iHeight; i++)
{
     for (int j = 0; j<iWidth; j++)
    {
        r = (double)pImg[(i*iWidth + j)*3 + 2];
        g = (double)pImg[(i*iWidth + j)*3 + 1];
        b = (double)pImg[(i*iWidth + j)*3 + 0];

         r= r * 0.299;
         g= g * 0.587;
         b= b * 0.144;

         gray = floor((r + g + b + 0.5));

         pImgGS[(iHeight-i-1)*iWidth + j] = gray;
     }
}
tl;dr: 创建一个公共路径。以明确定义的方式将所有内容转换为32位,并且不使用图像尺寸或坐标。将YCbCr转换(=灰度值计算)重构为单独的函数,这样更易于读取,并且运行速度完全相同

冗长的东西 首先,您似乎被步幅和偏移量混淆了。您看到的伪影是因为您在本应写入三个值时意外地写出了一个值(总共只有三分之一的数据)。
人们很容易对此感到困惑,但在这里发生这种情况是因为你做了一些原本不需要做的无用的事情。你从左到右、从上到下迭代坐标,并煞费苦心地计算每个位置数据中正确的字节偏移量。
然而,你正在做一个全屏效果,所以你真正想要的是在整个图像上迭代。谁在乎宽度和高度呢?你知道数据的开头,也知道长度。在整个blob上循环一次也可以做到这一点,只不过速度更快,代码模糊程度更低,获得数据的机会更少我错了

接下来,24位位图作为文件是常见的,但它们对于内存中的表示是非常不寻常的,因为这种格式很难访问并且不适合硬件。绘制这样的位图需要驱动程序或图形硬件进行大量工作(它可以工作,但不能很好地工作)因此,32位深度通常是更好、更快、更舒适的选择。访问程序更“自然”。
您可以非常简单地将24位转换为32位。对完整的位图数据进行迭代,并为每读取一个3字节元组写出一个完整的32位字。Windows位图忽略a通道(最高阶字节),因此只需将其保留为零或其他任何值

此外,没有8位灰度位图。这根本不存在。虽然存在看起来像灰度位图的位图,但实际上它们是调色板8位位图,
bmiColors
成员包含所有灰度值

因此,除非您能保证只处理您自己创建的图像,否则您不能仅依赖于值5和73分别对应于5/255和73/255灰度强度。可能是这样,但这通常是错误的假设。
为了保证正确性,您必须通过在调色板中查找索引(位图的灰度值实际上是索引)将8位灰度位图转换为真实颜色。否则,您可能会在调色板相反的位置加载灰度图像(因此5表示250,250表示5),或根本不是灰度的位图

所以…你想要转换24位和8位位图,两者都转换为32位深度。这意味着你在开始时只做一次所有令人讨厌的假设,其余的都是相同的公共路径。这是一件好事。
屏幕上显示的始终是一个32位位图,其中最上面的字节被忽略,最下面的三个字节都是相同的值,导致看起来像灰色阴影。这很简单,简单就是好的

请注意,如果您执行BT.601样式的YCbCr转换(如使用常数0.299、0.587和0.144所示),并且如果您的8位灰度图像是可感知的(这是您必须知道的,从文件中无法判断!),然后为了100%的正确性,您需要在从调色板8位转换为RGB时进行逆变换。否则,您的最终结果看起来几乎正确,但不完全正确。如果您的8位灰度卡是线性的,即创建时没有使用上述常量(同样,您必须知道,您无法从图像中分辨),您需要按原样复制所有内容(在这里,进行转换将使其看起来几乎正确,但并不完全正确)

关于RGB到灰度的转换,您不需要额外的灰度位图来保存以后不再需要的值。您可以从加载的位图中读取三个颜色值,计算Y,然后直接构建32位ARGB字,然后将其写入最终位图。这节省了一次完全无用的往返不必要的记忆

大概是这样的:

uint32_t* out = (uint32_t*) output_bitmap_data;

for(int i = 0; i < inputSize; i+= 3)
{
    uint8_t Y = calc_greyscale(in[0], in[1], in[2]);
    *out++ = (Y<<16) | (Y<<8) | Y;
}
uint32\u t*out=(uint32\u t*)输出位图数据;
对于(int i=0;i*out++=(Y
r*0.299;
实际上不起作用anything@VTT哦,好的。你能详细说明一下吗?我得到了一个类似的错误。
r*0.299;
将整数乘以双精度,结果不被使用。你应该写
double r\u dbl=static\u cast(r)* 0.299,我也认为你的源图像实际上可能是32 BPP。@ VTT谢谢。这有助于颜色,但我仍然有图像中的灰色条带,它只是一个适当的灰色现在。你只写三分之一的像素。
double r,g,b;
unsigned char gray;
long index=0;
for (int i = 0; i<iHeight; i++)
{
     for (int j = 0; j<iWidth; j++)
    {
        r = (double)pImg[index+ (j)*3 + 2];
        g = (double)pImg[index+ (j)*3 + 1];
        b = (double)pImg[index+ (j)*3 + 0];

         r= r * 0.299;
         g= g * 0.587;
         b= b * 0.144;

         gray = floor((r + g + b + 0.5));

         pImgGS[(iHeight-i-1)*iWidth + j] = gray;
     }
index =index +pitch;
}
pImgGS[(iHeight-i-1)*iWidth + j] = gray;
uint32_t* out = (uint32_t*) output_bitmap_data;

for(int i = 0; i < inputSize; i+= 3)
{
    uint8_t Y = calc_greyscale(in[0], in[1], in[2]);
    *out++ = (Y<<16) | (Y<<8) | Y;
}