直方图均衡化处理
概念
直方图均衡化(Histogram Equalization) 又称直方图平坦化,实质上是对图像进行非 线性拉伸,重新分配图像象元值,使一定灰度范围内象元值的数量大致相等。这样,原来直方图中间的峰顶部分对比度得到增强,而两侧的谷底部分对比度降低,输出图像的直方图是一 个较平的分段直方图:如果输出数据分段值较小的话,会产生粗略分类的视觉效果。直方图是表示数字图像中每一灰度出现频率的统计关系。直方图能给出图像灰度范围、 每个灰度的频度和灰度的分布、整幅图像的平均明暗和对比度等概貌性描述。灰度直方图是灰度级的函数, 反映的是图像中具有该灰度级像素的个数, 其横坐标是灰度级 r, 纵坐 标是该灰度级出现的频率( 即像素的个数) pr( r) , 整个坐标系描述的是图像灰度级的 分布情况, 由此可以看出图像的灰度分布特性, 即若大部分像素集中在低灰度区域, 图 像呈现暗的特性; 若像素集中在高灰度区域, 图像呈现亮的特性。由于这个算法只是算了灰度图像,所以加入处理彩色图像,只需要对图像 R G B 每个分量 进行直方图累计后拓展,后找到映射关系。
算法说明
![8db3fb187684e55ba28a428218badcec.png](https://img-blog.csdnimg.cn/img_convert/8db3fb187684e55ba28a428218badcec.png)
示例1
![44ad8c0327961cf65b73c9196e09448b.png](https://img-blog.csdnimg.cn/img_convert/44ad8c0327961cf65b73c9196e09448b.png)
原图
![c6fbcf907c52e5f27c6e414bee431d55.png](https://img-blog.csdnimg.cn/img_convert/c6fbcf907c52e5f27c6e414bee431d55.png)
处理之后
由于直方图均衡化处理的图片一般为灰度图像,所以处理彩色图像就会显得有些怪异,下面将给大家展示灰度图像的示例
示例2![517c8fb71d2622b19f7818453b24a352.png](https://img-blog.csdnimg.cn/img_convert/517c8fb71d2622b19f7818453b24a352.png)
原图
![8aef4229a8d4f4629133c7071bd4edc4.png](https://img-blog.csdnimg.cn/img_convert/8aef4229a8d4f4629133c7071bd4edc4.png)
处理后的效果
源码:
///// 程序名称:图像处理——直方图均衡化// 编译环境:Mictosoft Visual Studio 2013, EasyX_20200315(beta)// 作 者:luoyh <2864292458@qq.com>// 最后修改:2020-11-27//#include#includeclass Algorithm{public: Algorithm(IMAGE *img, int width, int heigth); void Histogram(); // 直方图private: IMAGE *pimg; int WIDTH; int HEIGHT;};Algorithm::Algorithm(IMAGE *img, int width, int height){ pimg = img; WIDTH = width; HEIGHT = height;};void Algorithm::Histogram() // 直方图{ DWORD* p_data = GetImageBuffer(pimg); int height = HEIGHT; int wide = WIDTH; double pr[256], pg[256], pb[256]; int size = HEIGHT * WIDTH; for (int p = 0; p <= 255; p++) { int nr = 0, ng = 0, nb = 0; for (int j = 0; j < height; j++) { for (int i = 0; i < wide; i++) { if (p == GetRValue(p_data[j*wide + i])) { nr++; } if (p == GetGValue(p_data[j*wide + i])) { ng++; } if (p == GetBValue(p_data[j*wide + i])) { nb++; } } } pr[p] = nr; pg[p] = ng; pb[p] = nb; } double sr[256] = { 0 }, sg[256] = { 0 }, sb[256] = { 0 }; double aver = 0; double aveg = 0; double aveb = 0; for (int i = 0; i <= 255; i++) { aver += pr[i] / size; sr[i] = aver; aveg += pg[i] / size; sg[i] = aveg; aveb += pb[i] / size; sb[i] = aveb; } double ssr[255] = { 0 }, ssg[255] = { 0 }, ssb[255] = { 0 }; for (int i = 0; i < 255; i++) { ssr[i] = (int)(((255 - 1) - 0) * sr[i] + 0.5); ssg[i] = (int)(((255 - 1) - 0) * sg[i] + 0.5); ssb[i] = (int)(((255 - 1) - 0) * sb[i] + 0.5); } int r = 0, g = 0, b = 0; double myr = 0, myg = 0, myb = 0; for (int j = 0; j < height; j++) { for (int i = 0; i < wide; i++) { while (GetRValue(p_data[j * wide + i]) != r) { r++; if (r == 255) break; } if (GetRValue(p_data[j * wide + i]) == r) { myr = ssr[r]; } r = 0; while (GetGValue(p_data[j * wide + i]) != g) { g++; if (g == 255) break; } if (GetGValue(p_data[j * wide + i]) == g) { myg = ssg[g]; } g = 0; while (GetBValue(p_data[j * wide + i]) != b) { b++; if (b == 255) break; } if (GetBValue(p_data[j * wide + i]) == b) { myb = ssb[b]; } b = 0; p_data[j * wide + i] = RGB(myr, myg, myb); } }};int main(){ int width = 0; int height = 0; IMAGE g_img; loadimage(&g_img, _T("src.jpg")); // 加载图片 width = g_img.getwidth(); height = g_img.getheight(); initgraph(width, height); putimage(0,0,&g_img); _getch(); Algorithm myA(&g_img, width, height); myA.Histogram(); putimage(0, 0, &g_img); _getch(); return 0;}
![b012eb13ef0a9fc3caef213d8074ad0a.png](https://img-blog.csdnimg.cn/img_convert/b012eb13ef0a9fc3caef213d8074ad0a.png)
人但有恒,事无不成