Image processing 改进灰度转换结果
这是彩色菜单: 这是同一个菜单,其中一些菜单项被禁用,位图设置为灰度: 转换为灰度的代码:Image processing 改进灰度转换结果,image-processing,mfc,cbitmap,Image Processing,Mfc,Cbitmap,这是彩色菜单: 这是同一个菜单,其中一些菜单项被禁用,位图设置为灰度: 转换为灰度的代码: auto col = GetRValue(pixel) * 0.299 + GetGValue(pixel) * 0.587 + GetBValue(pixel) * 0.114; pixel = RGB(col, col, col); 我是色盲,但似乎有些色盲看起来没什么不同。我想它首先与原色有关吧 如果能更明显地看出他们是残疾的,那就太好了。就像,
auto col = GetRValue(pixel) * 0.299 +
GetGValue(pixel) * 0.587 +
GetBValue(pixel) * 0.114;
pixel = RGB(col, col, col);
我是色盲,但似乎有些色盲看起来没什么不同。我想它首先与原色有关吧
如果能更明显地看出他们是残疾的,那就太好了。就像,这是非常明确的文字
我们能吗?对于非色盲的人来说,这是很明显的 只需对图像应用与文本相同的强度降低 我没有检查你的价值观。假设文本为白色(100%强度) 灰色文本的强度为50% 那么位图的最大强度也应该是50%
for each gray pixel:
pixel_value = pixel_value / max_pixel_value * gray_text_value
这样可以进一步降低每个位图的对比度,避免任何像素比文本更亮。对于没有色盲的人来说,这是非常明显的 只需对图像应用与文本相同的强度降低 我没有检查你的价值观。假设文本为白色(100%强度) 灰色文本的强度为50% 那么位图的最大强度也应该是50%
for each gray pixel:
pixel_value = pixel_value / max_pixel_value * gray_text_value
这样可以进一步降低每个位图的对比度,避免任何像素比文本更亮。这与您的问题没有直接关系,但由于您正在更改颜色,因此还可以修复突出的角点像素(所谓角点像素,我不是指位图矩形边缘的像素,我是指人类可识别图像的角点) 例如,在下图中,在页面的角落处有一个红色像素。我们希望找到那个红色像素并将其与背景色混合,这样它就不会突出 若要查找角点像素,请检查左侧和顶部的像素,如果左侧和顶部都是背景色,则有一个角点像素。对右上角、左下角和右下角重复相同的操作。将角点像素与背景混合 您可以按照zett42的建议更改alpha透明度,而不是更改为灰度
void change(HBITMAP hbmp, bool enabled)
{
if(!hbmp)
return;
HDC memdc = CreateCompatibleDC(nullptr);
BITMAP bm;
GetObject(hbmp, sizeof(bm), &bm);
int w = bm.bmWidth;
int h = bm.bmHeight;
BITMAPINFO bi = { sizeof(BITMAPINFOHEADER), w, h, 1, 32, BI_RGB };
std::vector<uint32_t> pixels(w * h);
GetDIBits(memdc, hbmp, 0, h, &pixels[0], &bi, DIB_RGB_COLORS);
//assume that the color at (0,0) is the background color
uint32_t old_color = pixels[0];
//this is the new background color
uint32_t bk = GetSysColor(COLOR_MENU);
//swap RGB with BGR
uint32_t new_color = RGB(GetBValue(bk), GetGValue(bk), GetRValue(bk));
//define lambda functions to swap between BGR and RGB
auto bgr_r = [](uint32_t color) { return GetBValue(color); };
auto bgr_g = [](uint32_t color) { return GetGValue(color); };
auto bgr_b = [](uint32_t color) { return GetRValue(color); };
BYTE new_red = bgr_r(new_color);
BYTE new_grn = bgr_g(new_color);
BYTE new_blu = bgr_b(new_color);
//change background and modify disabled bitmap
for(auto &p : pixels)
{
if(p == old_color)
{
p = new_color;
}
else if(!enabled)
{
//blend color with background, similar to 50% alpha
BYTE red = (bgr_r(p) + new_red) / 2;
BYTE grn = (bgr_g(p) + new_grn) / 2;
BYTE blu = (bgr_b(p) + new_blu) / 2;
p = RGB(blu, grn, red); //<= BGR/RGB swap
}
}
//fix corner edges
for(int row = h - 2; row >= 1; row--)
{
for(int col = 1; col < w - 1; col++)
{
int i = row * w + col;
if(pixels[i] != new_color)
{
//check the color of neighboring pixels:
//if that pixel has background color,
//then that pixel is the background
bool l = pixels[i - 1] == new_color; //left pixel is background
bool r = pixels[i + 1] == new_color; //right ...
bool t = pixels[i - w] == new_color; //top ...
bool b = pixels[i + w] == new_color; //bottom ...
//we are on a corner pixel if:
//both left-pixel and top-pixel are background or
//both left-pixel and bottom-pixel are background or
//both right-pixel and bottom-pixel are background or
//both right-pixel and bottom-pixel are background
if(l && t || l && b || r && t || r && b)
{
//blend corner pixel with background
BYTE red = (bgr_r(pixels[i]) + new_red) / 2;
BYTE grn = (bgr_g(pixels[i]) + new_grn) / 2;
BYTE blu = (bgr_b(pixels[i]) + new_blu) / 2;
pixels[i] = RGB(blu, grn, red);//<= BGR/RGB swap
}
}
}
}
SetDIBits(memdc, hbmp, 0, h, &pixels[0], &bi, DIB_RGB_COLORS);
DeleteDC(memdc);
}
这与您的问题没有直接关系,但由于您正在更改颜色,您还可以修复突出的角点像素(角点像素不是指位图矩形边缘的像素,而是指人类可识别图像的角点) 例如,在下图中,在页面的角落处有一个红色像素。我们希望找到那个红色像素并将其与背景色混合,这样它就不会突出 若要查找角点像素,请检查左侧和顶部的像素,如果左侧和顶部都是背景色,则有一个角点像素。对右上角、左下角和右下角重复相同的操作。将角点像素与背景混合 您可以按照zett42的建议更改alpha透明度,而不是更改为灰度
void change(HBITMAP hbmp, bool enabled)
{
if(!hbmp)
return;
HDC memdc = CreateCompatibleDC(nullptr);
BITMAP bm;
GetObject(hbmp, sizeof(bm), &bm);
int w = bm.bmWidth;
int h = bm.bmHeight;
BITMAPINFO bi = { sizeof(BITMAPINFOHEADER), w, h, 1, 32, BI_RGB };
std::vector<uint32_t> pixels(w * h);
GetDIBits(memdc, hbmp, 0, h, &pixels[0], &bi, DIB_RGB_COLORS);
//assume that the color at (0,0) is the background color
uint32_t old_color = pixels[0];
//this is the new background color
uint32_t bk = GetSysColor(COLOR_MENU);
//swap RGB with BGR
uint32_t new_color = RGB(GetBValue(bk), GetGValue(bk), GetRValue(bk));
//define lambda functions to swap between BGR and RGB
auto bgr_r = [](uint32_t color) { return GetBValue(color); };
auto bgr_g = [](uint32_t color) { return GetGValue(color); };
auto bgr_b = [](uint32_t color) { return GetRValue(color); };
BYTE new_red = bgr_r(new_color);
BYTE new_grn = bgr_g(new_color);
BYTE new_blu = bgr_b(new_color);
//change background and modify disabled bitmap
for(auto &p : pixels)
{
if(p == old_color)
{
p = new_color;
}
else if(!enabled)
{
//blend color with background, similar to 50% alpha
BYTE red = (bgr_r(p) + new_red) / 2;
BYTE grn = (bgr_g(p) + new_grn) / 2;
BYTE blu = (bgr_b(p) + new_blu) / 2;
p = RGB(blu, grn, red); //<= BGR/RGB swap
}
}
//fix corner edges
for(int row = h - 2; row >= 1; row--)
{
for(int col = 1; col < w - 1; col++)
{
int i = row * w + col;
if(pixels[i] != new_color)
{
//check the color of neighboring pixels:
//if that pixel has background color,
//then that pixel is the background
bool l = pixels[i - 1] == new_color; //left pixel is background
bool r = pixels[i + 1] == new_color; //right ...
bool t = pixels[i - w] == new_color; //top ...
bool b = pixels[i + w] == new_color; //bottom ...
//we are on a corner pixel if:
//both left-pixel and top-pixel are background or
//both left-pixel and bottom-pixel are background or
//both right-pixel and bottom-pixel are background or
//both right-pixel and bottom-pixel are background
if(l && t || l && b || r && t || r && b)
{
//blend corner pixel with background
BYTE red = (bgr_r(pixels[i]) + new_red) / 2;
BYTE grn = (bgr_g(pixels[i]) + new_grn) / 2;
BYTE blu = (bgr_b(pixels[i]) + new_blu) / 2;
pixels[i] = RGB(blu, grn, red);//<= BGR/RGB swap
}
}
}
}
SetDIBits(memdc, hbmp, 0, h, &pixels[0], &bi, DIB_RGB_COLORS);
DeleteDC(memdc);
}
我只对菜单项图像本身应用灰度。文本由MFC框架处理。你能在实践中给我看一下你的建议吗?谢谢。@AndrewTruckle截图,使用允许在鼠标位置显示像素值的许多免费图像程序之一,找出文本使用的灰度值。屏幕显示为灰色out text的亮度为92(在inverval 0-255中)。您只需计算像素值,然后确定最大像素值,并使用该值将值标准化为[0-92]或者简单地降低标准化值,直到您满意为止。屏幕截图中显示的暗主题可能会使亮度降低,但我相信如果使用亮主题,情况会更糟。这就是为什么我会将图像的整体透明度更改为50%,以便图像与背景混合,而不管背景是否为暗主题声音是暗的或亮的。我只对菜单项图像本身应用灰度。文本由MFC框架处理。请在实践中向我展示您的建议好吗?谢谢。@AndrewTruckle截图,使用允许在鼠标上显示像素值的众多免费图像程序之一,找出文本的强度位置。灰显文本的亮度为92(在inverval 0-255中)。您只需计算像素值,然后确定最大像素值,并使用该值将值规格化为[0-92]或者简单地降低标准化值,直到您满意为止。屏幕截图中显示的暗主题可能会使亮度降低,但我相信如果使用亮主题,情况会更糟。这就是为什么我会将图像的整体透明度更改为50%,以便图像与背景混合,而不管背景是否为暗主题颜色是暗的或浅的。彩色位图看起来比灰色位图更糟糕,因为它们在暗背景下具有锐利的浅色边缘。若要修复此问题,请编辑位图,例如在箭头末端找到浅灰色像素,将其更改为白色或任何背景颜色。或者,您可以将其保留。这可能与灯光有关主题背景。大多数人使用浅色背景主题,因此大多数客户都应该感到高兴!最后一个值应该是
0.114
,而不是0.144
,并且需要采用RGB
值,正如@BarmakShemirani所指出的那样,我处理了我的问题代码,而不是答案代码。哦,实际的屏幕截图是正确的值ues。我建议使用32 bpp图像和alpha通道来去除锯齿状边缘(尤其是在“周末会议”图标上,它看起来非常难看)。对于禁用的图像,除了灰度效果之外,或作为灰度效果的替代,将整体透明度设置为50%左右。我将禁用的图像变暗,然后我会更清楚地看到它们被禁用。彩色位图看起来比灰色位图更差,因为它们