Ex3:用CImg编写灰度图像直方图均衡化和颜色转换
来源:互联网 发布:魅族系统升级清除数据 编辑:程序博客网 时间:2024/05/16 03:31
【2017/3/21更新】
自己用了RGB -> HSI模型来进行直方图均衡化。
后面用了RGB-> Lab模型进行颜色转换。
测试样例:
原图:
直方图均衡化:
灰度图:
灰度图直方图均衡化:
原图:
直方图均衡化:
灰度图:
灰度图直方图均衡化:
实现代码:
理论上什么图片都可以运行成功了。
其实RGB->HSI->RGB的公式搜一下就有,实现数学公式就好,主要是对HSI中的I通道进行直方图均衡化,因为I代表亮度,理论上不会影响色彩,不容易失真。
其实代码应该写成一个 类 封装起来更好。
#include "CImg.h"#include <iostream>#include <cmath>#define PI 3.141using namespace std;using namespace cimg_library;CImg<float> toGrayScale(CImg<float> img) { CImg<float> grayscaled = img; cimg_forXY(img, x, y) { int r = img(x, y, 0); int g = img(x, y, 1); int b = img(x, y, 2); double newValue = (r * 0.2126 + g * 0.7152 + b * 0.0722); grayscaled(x, y, 0) = newValue; grayscaled(x, y, 1) = newValue; grayscaled(x, y, 2) = newValue; } return grayscaled;}CImg<float> his_equalization(CImg<float> img_) { float statistics[256]; float cumulative[256]; float probability[256]; int rows = img_._width; int cols = img_._height; for (int i = 0; i < 256; i++) { statistics[i] = 0; cumulative[i] = 0; probability[i] = 0; } CImg<float > img = img_; float totalpixels = rows * cols; cimg_forXY(img, x, y) { float r = img(x, y, 0); float g = img_(x, y, 1); float b = img_(x, y, 2); float min = r; if(min > g) min = g; if(min > b) min = b; float t1 = 0.5*((r-g)+(r-b)); float t2 = pow((r-g)*(r-g)+(r-b)*(g-b)+0.0000001, 0.5); float angle = acos(t1/t2) * 180 / 3.14; float h = 0; if(b <= g) h = angle / 360.0; else h = (360.0- angle) / 360.0; float s = 1 - 3.0/(r + b + g) * min; float i = (r + b + g) / 3.0; img(x, y, 0) = h; img(x, y, 1) = s; img(x, y, 2) = i; } /*******his*******************/ cimg_forXY(img, x, y) { int index = (int)img(x, y, 2); statistics[index]++; } for (int i = 0; i < 256; i++) { probability[i] = statistics[i] / totalpixels; } for (int i = 0; i < 256; i++) { for (int j = 0; j <= i; j++) { cumulative[i] += probability[j]; } } cimg_forXY(img, x, y) { int index = (int)img(x, y, 2); img(x, y, 2) = (int)(255.0 * cumulative[index]); } float h, s, i; float r, g, b; r = g = b = 0; cimg_forXY(img, x, y) { h = img(x, y, 0); s = img(x, y, 1); i = img(x, y, 2); h = h * 360; float h_; if(h >= 0 && h < 120) { h_ = h * PI / 180; b = i * (1 - s); r = i * (1 + s * cos(h_) / cos(PI/3 - h_)); g = 3*i - (r + b); } else if( h >= 120 && h < 240) { h = h - 120; h_ = h * PI / 180; r = i * (1 - s); g = i * (1 + s * cos(h_)/cos(PI/3 - h_)); b = 3*i - (r + g); } else if (h >= 240 && h < 360) { h = h - 240; h_ = h * PI / 180; g = i * (1 - s); b = i * (1 + s * cos(h_)/cos(PI/3 - h_)); r = 3*i - (b + g); } if(r > 255) r = 255; if(g > 255) g = 255; if(b > 255) b = 255; //cout << r << ", " << g << ", " << b << endl; img(x, y, 0) = r; img(x, y, 1) = g; img(x, y, 2) = b; } return img;}
Lab颜色转换
source图:
target图:
transfer后:
代码如下:
#ifndef COLORTRANSFERBYLAB_H#define COLORTRANSFERBYLAB_H#include <iostream>#include <cmath>#include "CImg.h"using namespace std;using namespace cimg_library;class colorTransferbylab { private: CImg<float> source; CImg<float> target; CImg<float> result; public: colorTransferbylab(); colorTransferbylab(CImg<float> s, CImg<float> t); void setImages(CImg<float> s, CImg<float> t); CImg<float> getSource(); CImg<float> getTarget(); CImg<float> getResult(); void colorTransfer();};colorTransferbylab::colorTransferbylab() { }colorTransferbylab::colorTransferbylab(CImg<float> s, CImg<float> t) { source = s; target = t; result = s;}void colorTransferbylab::setImages(CImg<float> s, CImg<float> t) { source = s; source = t; result = s;}CImg<float> colorTransferbylab::getSource() { return source;}CImg<float> colorTransferbylab::getTarget() { return target;}CImg<float> colorTransferbylab::getResult() { return result;}void colorTransferbylab::colorTransferbylab::colorTransfer() { float sum1[3], sum2[3], sum1_squ[3], sum2_squ[3]; float mean1[3], mean2[3], vari1[3], vari2[3]; int width1 = source._width, height1 = source._height; int total1 = width1*height1; int width2 = target._width, height2 = target._height; int total2 = width2*height2; for (int i = 0; i < 3; i++) { sum1[i] = sum2[i] = sum1_squ[i] = sum2_squ[i] = 0; mean1[i] = mean2[i] = vari1[i] = vari2[i] = 0; } // RGB ----->lab cimg_forXY(source, x, y) { float r = source(x, y, 0); float g = source(x, y, 1); float b = source(x, y, 2); float L = 0.3811 * r + 0.5783 * g + 0.0402 * b; float M = 0.1967 * r + 0.7244 * g + 0.0782 * b; float S = 0.0241 * r + 0.1288 * g + 0.8444 * b; if(L == 0) L = 1; if(M == 0) M = 1; if(S == 0) S = 1; L = log(L); M = log(M); S = log(S); float l = (1.0/sqrt(3)) * (L + M + S); float alpha = 1.0/sqrt(6) * L + 1.0/sqrt(6) * M - 2.0/sqrt(6) * S; float beta = 1.0/sqrt(2) * L - 1.0/sqrt(2) * M; result(x, y, 0) = l; result(x, y, 1) = alpha; result(x, y, 2) = beta; //cout << l << ", " << alpha << ", " << beta << endl; sum1[0] += l; sum1[1] += alpha; sum1[2] += beta; } mean1[0] = sum1[0] / total1; mean1[1] = sum1[1] / total1; mean1[2] = sum1[2] / total1; cimg_forXY(result, x, y) { sum1_squ[0] += (result(x, y, 0) - mean1[0]) * (result(x, y, 0) - mean1[0]); sum1_squ[1] += (result(x, y, 1) - mean1[1]) * (result(x, y, 1) - mean1[1]); sum1_squ[2] += (result(x, y, 2) - mean1[2]) * (result(x, y, 2) - mean1[2]); } vari1[0] = sqrt(sum1_squ[0] / total1); vari1[1] = sqrt(sum1_squ[1] / total1); vari1[2] = sqrt(sum1_squ[2] / total1); // target RGB ------->lab cimg_forXY(target, x, y) { float r = target(x, y, 0); float g = target(x, y, 1); float b = target(x, y, 2); float L = 0.3811 * r + 0.5783 * g + 0.0402 * b; float M = 0.1967 * r + 0.7244 * g + 0.0782 * b; float S = 0.0241 * r + 0.1288 * g + 0.8444 * b; if(L == 0) L = 1; if(M == 0) M = 1; if(S == 0) S = 1; L = log(L); M = log(M); S = log(S); float l = (1.0/sqrt(3)) * (L + M + S); float alpha = 1.0/sqrt(6) * L + 1.0/sqrt(6) * M - 2.0/sqrt(6) * S; float beta = 1.0/sqrt(2) * L - 1.0/sqrt(2) * M; target(x, y, 0) = l; target(x, y, 1) = alpha; target(x, y, 2) = beta; sum2[0] += l; sum2[1] += alpha; sum2[2] += beta; } mean2[0] = sum2[0] / total2; mean2[1] = sum2[1] / total2; mean2[2] = sum2[2] / total2; cimg_forXY(target, x, y) { sum2_squ[0] += (target(x, y, 0) - mean2[0]) * (target(x, y, 0) - mean2[0]); sum2_squ[1] += (target(x, y, 1) - mean2[1]) * (target(x, y, 1) - mean2[1]); sum2_squ[2] += (target(x, y, 2) - mean2[2]) * (target(x, y, 2) - mean2[2]); } vari2[0] = sqrt(sum2_squ[0] / total2); vari2[1] = sqrt(sum2_squ[1] / total2); vari2[2] = sqrt(sum2_squ[2] / total2); //transfer between images cimg_forXY(result, x, y) { result(x, y, 0) = (result(x, y, 0) - mean1[0]) * vari2[0] / vari1[0] + mean2[0]; result(x, y, 1) = (result(x, y, 1) - mean1[1]) * vari2[1] / vari1[1] + mean2[1]; result(x, y, 2) = (result(x, y, 2) - mean1[2]) * vari2[2] / vari1[2] + mean2[2]; } // lab -----> RGB cimg_forXY(target, x, y) { float L = sqrt(3)/3 * target(x, y, 0) + sqrt(6)/6 * target(x, y, 1) + sqrt(2)/2 * target(x, y, 2); float M = sqrt(3)/3 * target(x, y, 0) + sqrt(6)/6 * target(x, y, 1) - sqrt(2)/2 * target(x, y, 2); float S = sqrt(3)/3 * target(x, y, 0) - sqrt(6)/3 * target(x, y, 1); L = pow(2.71828, L); M = pow(2.71828, M); S = pow(2.71828, S); target(x, y, 0) = 4.4679 * L - 3.5873 * M + 0.1193 * S; target(x, y, 1) = -1.2186 * L + 2.3809 * M - 0.1624 * S; target(x, y, 2) = 0.0497 * L - 0.2439 * M + 1.2045 * S; } cimg_forXY(result, x, y) { float L = sqrt(3)/3 * result(x, y, 0) + sqrt(6)/6 * result(x, y, 1) + sqrt(2)/2 * result(x, y, 2); float M = sqrt(3)/3 * result(x, y, 0) + sqrt(6)/6 * result(x, y, 1) - sqrt(2)/2 * result(x, y, 2); float S = sqrt(3)/3 * result(x, y, 0) - sqrt(6)/3 * result(x, y, 1); L = pow(2.71828, L); M = pow(2.71828, M); S = pow(2.71828, S); result(x, y, 0) = 4.4679 * L - 3.5873 * M + 0.1193 * S; result(x, y, 1) = -1.2186 * L + 2.3809 * M - 0.1624 * S; result(x, y, 2) = 0.0497 * L - 0.2439 * M + 1.2045 * S; }}#endif
0 0
- Ex3:用CImg编写灰度图像直方图均衡化和颜色转换
- [图像]图像灰度均衡化和灰度直方图(Matlab实现)
- OpenCV 图像增强—直方图均衡化和灰度拉伸
- 图像处理opencv2-灰度直方图以及灰度直方图均衡化
- 图像的灰度化,直方图均衡化
- 灰度图像直方图均衡处理
- [计算机视觉] CImg库绘制图像灰度直方图
- 灰度直方图均衡化
- 灰度图像--图像增强 直方图均衡化(Histogram equalization)
- 灰度图像直方图的创建与灰度图像直方图的均衡化[代码与运行结果]
- 图像直方图均衡和直方图规定化
- 灰度图像直方图的均衡化与规定化
- Python cv2 图像自适应灰度直方图均衡化处理
- opencv 颜色直方图(灰度图,均衡化,对比,描绘颜色直方图)
- Delphi图像处理 -- 灰度化和灰度直方图
- 直方图均衡化-灰度图
- 灰度直方图及直方图均衡化
- 灰度直方图之直方图均衡化
- Idea Debug调试介绍
- 浅析沟通与人际关系学
- outguess 使用方法
- 实验吧密码学CTF--chinese hacker
- 【MyBatis学习03】调用Mapper映射的3种使用方式
- Ex3:用CImg编写灰度图像直方图均衡化和颜色转换
- 学习日记-内部类,
- 循环队列实现(通过设置标志位tag位判断空队满队)
- 交叉编译ncurses-6.0和minicom到ARM板
- [C++]Vector简介
- 数据库概述
- vm模板
- 1004
- tomcat解决某个文件读取失败(例如:以汉字命名的一张图片)的问题