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
原创粉丝点击