参考公式处:https://hacpai.com/article/1359968457263
使用公式如下:
Gray = (R+B+G)/3
Gray = (R*299 + G*587 + B*114 + 500) / 1000
Gray = (R^2.2 * 0.2973 + G^2.2 * 0.6274 + B^2.2 * 0.0753)^(1/2.2)
这三条公式其实一开始误导了我,让我以为直接抽出RGB值后相加就是最终结果了,但很遗憾的,并不是。
接下来,我会分别展示三个使用了该三种公式的函数,都是自己根据公式理解到的函数写法:
//平均值法
void ToGray_three(COLORREF& color) {
//公式 R=G=B=(R+G+B)/3
//Gray=R+G+B
static COLORREF R;
R = ((GetRValue(color) + GetGValue(color) + GetBValue(color)) / 3);
color = R + (R << 8) + (R << 16);
}
//心理学公式的最佳权重法
void ToGray_good(COLORREF& color) {
//公式 R=G=B= (R*299 + G*587 + B*114 + 500) / 1000
//Gray=R+G+B
static COLORREF R;
R = (GetRValue(color) * 229 + GetGValue(color) * 587 + GetBValue(color) * 114 + 500) / 1000;
color = R + (R << 8) + (R << 16);
}
//Pthotoshop用的灰度算法
void ToGray_Photoshop(COLORREF& color) {
//公式 R=G=B=(R^2.2 * 0.2973 + G^2.2 * 0.6274 + B^2.2 * 0.0753)^(1/2.2)
//Gray=R+G+B
static COLORREF R;
R = pow((pow(GetRValue(color),2.2)*0.2973+ pow(GetGValue(color),2.2)*0.6274 + pow(GetBValue(color),2.2)*0.0753),1/2.2);
color = R + (R << 8) + (R << 16);
}
以上三个函数都分别以不同的方式实现了图像灰度化
下面我给出一个可运行例子及执行结果图:
#include <graphics.h>
#include <conio.h>//用来暂停_getch,可以不要,
#include <math.h>//用pow来计算幂,用且仅用在了ToGray_Photoshop上
void ToGray_three(COLORREF& color) {
//公式 R=G=B=(R+G+B)/3
//Gray=R+G+B
static COLORREF R;
R = ((GetRValue(color) + GetGValue(color) + GetBValue(color)) / 3);
color = R + (R << 8) + (R << 16);
}
void ToGray_good(COLORREF& color) {
//公式 R=G=B= (R*299 + G*587 + B*114 + 500) / 1000
//Gray=R+G+B
static COLORREF R;
R = (GetRValue(color) * 229 + GetGValue(color) * 587 + GetBValue(color) * 114 + 500) / 1000;
color = R + (R << 8) + (R << 16);
}
void ToGray_Photoshop(COLORREF& color) {
//公式 R=G=B=(R^2.2 * 0.2973 + G^2.2 * 0.6274 + B^2.2 * 0.0753)^(1/2.2)
//Gray=R+G+B
static COLORREF R;
R = pow((pow(GetRValue(color),2.2)*0.2973+ pow(GetGValue(color),2.2)*0.6274 + pow(GetBValue(color),2.2)*0.0753),1/2.2);
color = R + (R << 8) + (R << 16);
}
int main() {
int i, j;
IMAGE img;
loadimage(&img, TEXT("d.jpg"));
int w = img.getwidth();
int h = img.getheight();
IMAGE img1(img), img2(img), img3(img);
DWORD *imgp1 = GetImageBuffer(&img1);
DWORD *imgp2 = GetImageBuffer(&img2);
DWORD *imgp3 = GetImageBuffer(&img3);
for (i = 0; i < h; ++i)
for (j = 0; j < w; ++j) {
ToGray_three(imgp1[i*w + j]);
ToGray_good(imgp2[i*w + j]);
ToGray_Photoshop(imgp3[i*w + j]);
}
initgraph(w*3, h);
putimage(0, 0, &img1);
putimage(w, 0, &img2);
putimage(w*2, 0, &img3);
_getch();
closegraph();
}
从左到右分别是:
平均值法(速度很快,0~1ms)
心理学公式的最佳权重法(速度快,1~2ms)
Pthotoshop用的灰度算法(速度慢,110~120ms)
【时间来源:来自VS2017下的release的调试模式运行结果,使用clock函数进行计时,该时间是完全灰度化一张示例图所使用的时间】
关于灰度化的图像质量方面,我这边了解到的信息是:从左往右 就是 从不那么好到好
但这个我并没有找很多图做大量的测试,具体在图像上进行灰度化是什么表现,就待各位到时候去对比了。
好的,那么easyx的图像灰度化的三种方法及其示例就写到这里就完毕了。
最后:
写完这三个函数后,我试图去简化它,于是就有了这么如下一个问题:
存在一个无符号整型变量,他的值是0x00000058,现在整个程序就这一个可以使用的无符号整型变量,且不能借助任何其他变量,只能操作这一个无符号整型变量,对它运算。
那么如何运算,使得他的值变为0x00585858呢?
这个问题是我在想能不能把这个三个函数都写成宏函数时总结出来的一个问题,不过,现在看来是不能的样子,但也算是想过简化,就放在后面,作为本篇博客的结尾。