ITKeyword,专注技术干货聚合推荐

注册 | 登录

图片对比度增强

分享于

2020腾讯云双十一活动,全年最低!!!(领取3500元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1073

2020阿里云最低价产品入口,含代金券(新老用户有优惠),
地址https://www.aliyun.com/minisite/goods

推荐:opencv 彩色图像对比度增强

一般地,图像对比度都是在灰度图上进行增强,这在我的一篇文章中已经给出了实现方法(http://blog.csdn.net/abcjennifer/article/details/7401921),最通常的办

简介

本篇主要讲解利用直方图均衡化和使用模糊集合灰度变换方式来优化图片对比度,并直观显示出这两种方式下的优化效果,和优化后图片的直方图分布情况。 直方图显示

开始讲图片对比度优化之前,需要先了解如何直观显示出图片的直方图,该方式在本篇后续中常用到,所以提到最开始先讲。这里直接使用opencv实现,具体代码如下: 具体代码 #include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv/cv.h>

using namespace cv; IplImage *DrawHistogram(CvHistogram *hist,float scaleX = 1,float scaleY = 1){

float histMax = 0;

cvGetMinMaxHistValue(hist,0,&histMax,0,0);

IplImage *imgHist = cvCreateImage(cvSize(256*scaleX,64*scaleY),8,1);

cvZero(imgHist);

for(int i=0;i<255;i++){

float histValue = cvQueryHistValue_1D(hist,i);

float nextValue = cvQueryHistValue_1D(hist,i+1);

CvPoint pt1 = cvPoint(i*scaleX,64*scaleY);

CvPoint pt2 = cvPoint((i+1)*scaleX,64*scaleY);

CvPoint pt3 = cvPoint((i+1)*scaleX,64*scaleY - (nextValue/histMax) * 64*scaleY);

CvPoint pt4 = cvPoint(i*scaleX,64*scaleY - (histValue/histMax) * 64*scaleY);

int numPts = 5;

CvPoint pts[5];

pts[0] = pt1;

pts[1] = pt2;

pts[2] = pt3;

pts[3] = pt4;

pts[4] = pt1;

cvFillConvexPoly(imgHist,pts,numPts,cvScalar(255));

}

return imgHist;} int main(int argc , char** argv){

cv::Mat image;

int dims = 1;

int size = 256;

float range[] = {0,255};

float* ranges[] = {range};

Mat mat;

IplImage src;

if(argc < 2){

printf("Please input picture!\n");

return -1;

}

mat = imread(argv[1], 0);

src = mat;

cvShowImage("src", &src);

CvHistogram *hist = cvCreateHist(dims,&size,CV_HIST_ARRAY,ranges,1);

cvClearHist(hist);

IplImage *imgGray = cvCreateImage(cvGetSize(&src),8,1);

cvSplit(&src,imgGray, NULL, NULL, NULL);

cvCalcHist(&imgGray, hist, 0, 0);

IplImage *histGray = DrawHistogram(hist);

cvClearHist(hist);

cvShowImage("Gray",histGray);

cv::waitKey(0);

return 0;} 效果演示

具体代码内容就不细讲了,结果显示如下:

直方图均衡化

该方式的实现,网上已经有很多例子了,这里提出来讲下,是为了方便和模糊集合灰度变换方式做效果对比。 具体代码 #include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv/cv.h>

using namespace cv; int main(int argc , char** argv){

cv::Mat image;

int size = 256;

Mat mat;

IplImage src;

int i, j, width, height;

int c[size];

double p[size];

CvScalar s1;

double max, min;

if(argc < 2){

printf("Please input picture!\n");

return -1;

}

mat = imread(argv[1], 0);

src = mat;

imshow("src", mat);

width = mat.rows;

height = mat.cols;

uchar* ptr = mat.ptr(0);

for(i=0; i<size; i++){

p[i] = 0;

c[i] = 0;

}

max=min=ptr[0];

for(i=0; i<width; i++){

for(j=0;j<height; j++){

int k;

s1 = cvGet2D(&src, i, j);

k = (int)s1.val[0];

c[k]++;

if(max<s1.val[0]){

max=s1.val[0];

}else if(min>s1.val[0]){

min=s1.val[0];

}

}

}

printf("min:%lf, max:%lf\n", min, max);

for(i=0;i<size;i++){

if(i > 0){

p[i] += p[i - 1];

}

p[i] += ((double)c[i])/((double)(width*height));

printf("p[%d]:%lf, c[%d]:%d\n", i, p[i], i, c[i]);

}

for(i=0; i<width; i++){

for(j=0; j<height; j++){

s1 = cvGet2D(&src, i, j);

s1.val[0] = p[(int)s1.val[0]] * (max-min) + min;

cvSet2D(&src, i, j, s1);

}

}

imshow("dst", mat);

imwrite("dst1.png", mat);

cv::waitKey(0);

return 0;} 代码讲解

这里只讲解下相关的核心代码:1、找到图像中最大像素、最小像素值、同时统计出图像所有像素值在[0, 255]范围内出现的数 max=min=ptr[0];for(i=0; i<width; i++){for(j=0;j<height; j++){

int k;

s1 = cvGet2D(&src, i, j);

k = (int)s1.val[0];

c[k]++;

if(max<s1.val[0]){

max=s1.val[0];

}else if(min>s1.val[0]){

min=s1.val[0];

}

}} 2、从0开始到255,依次叠加到当前像素数量的概率。 for(i=0;i<size;i++){if(i > 0){

p[i] += p[i - 1];}p[i] += ((double)c[i])/((double)(width*height));} 3、从新在min到max范围内, 根据之前统计的像素概率,重新映射调整像素值,生成新图像。 for(i=0; i<width; i++){

for(j=0; j<height; j++){s1 = cvGet2D(&src, i, j);s1.val[0] = p[(int)s1.val[0]] * (max-min) + min;cvSet2D(&src, i, j, s1);

}}imshow(&

推荐:图像处理中的直方图应用(通过直方图均衡化增强图像对比度)

直方图就是对数据进行统计,将统计值组织到一系列事先定义好的bin(直方图中的柱子)中。bin中的数值是从数据中计算出的特征的统计量,这些数据可以是诸如梯度

quot;dst", mat);imwrite("dst1.png", mat); 结果显示

显示的结果如下:

模糊度集合变换

接下来是看下,模糊度集合变换的实现。相关原理背景请看考<数字图像处理 第三版> 116页。该方式的核心原理为公式:

公式中的Udark、Ugray、Ubright由对应的当前像素点,根据右边曲线图来计算获得。Vd = 0,表示全黑;Vg = 127, 表示中间灰度;Vb = 255,表示白。Vo表示生成的结果图像当前像素值。 具体代码 #include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv/cv.h>

using namespace cv; #define throDark 30#define throMid 100#define throBright 170 double getUdark(double num){

double tmpUdark;

if(num <= throDark){

tmpUdark = 1;

}else if((num > throDark) && (num <= throMid)){

tmpUdark

= ((double)(throMid - num)) / ((double)(throMid - throDark));

}else{

tmpUdark = 0;

}

return tmpUdark;} double getUmid(double num){

double tmpUmid;

if((num > throDark) && (num < throMid)){

tmpUmid

= (num - throDark) / (throMid - throDark);

}else if((num >= throMid) && (num < throBright)){

tmpUmid

= (throBright - num) / (throBright - throMid);

}

else{

tmpUmid = 0;

}

return tmpUmid;} double getUbright(double num){

double tmpUbright;

if(num <= throMid){

tmpUbright = 0;

}else if((num > throMid) && (num <= throBright)){

tmpUbright

= (num - throMid) / (throBright - throMid);

}else{

tmpUbright = 1;

}

return tmpUbright;} int main(int argc , char** argv){

cv::Mat image;

Mat mat;

IplImage src;

int i, j, width, height;

CvScalar s1;

int Uall;

double tmp, Udark, Umid, Ubright;

if(argc < 2){

printf("Please input picture!\n");

return -1;

}

mat = imread(argv[1], 0);

src = mat;

imshow("src", mat);

width = mat.rows;

height = mat.cols;

uchar* ptr = mat.ptr(0);

for(i=0; i<width; i++){

for(j=0;j<height; j++){

s1 = cvGet2D(&src, i, j);

Udark

= getUdark(s1.val[0]);

Umid

= getUmid(s1.val[0]);

Ubright = getUbright(s1.val[0]);

s1.val[0] = (0 * Udark + 127 * Umid + 255 * Ubright) / (Udark + Umid + Ubright);//

printf("Udark:%lf, Umid:%lf, Ubright:%lf, s1.val[0]%lf\n", Udark, Umid, Ubright, s1.val[0]);

cvSet2D(&src, i, j, s1);

}

}

imshow("dst", mat);

imwrite("dst2.png", mat);

cv::waitKey(0);

return 0;} 代码讲解

1、throDark、throMid、throBright对应的就是前面曲线图中:Udark等的阀值。曲线图中阀值为63/127/191。根据图像,这些阀值我们可以自行调整。 #define throDark 30#define throMid 100#define throBright 170

2、getUdark、getUmid、getUbright三个函数通过传入的像素值,分别返回曲线图中对应的Udark,Ugray, Ubright值。 double getUdark(double num){

double tmpUdark;

if(num <= throDark){

tmpUdark = 1;

}else if((num > throDark) && (num <= throMid)){

tmpUdark

= ((double)(throMid - num)) / ((double)(throMid - throDark));

}else{

tmpUdark = 0;

}

return tmpUdark;} double getUmid(double num){

double tmpUmid;

if((num > throDark) && (num < throMid)){

tmpUmid

= (num - throDark) / (throMid - throDark);

}else if((num >= throMid) && (num < throBright)){

tmpUmid

= (throBright - num) / (throBright - throMid);

}

else{

tmpUmid = 0;

}

return tmpUmid;} double getUbright(double num){

double tmpUbright;

if(num <= throMid){

tmpUbright = 0;

}else if((num > throMid) && (num <= throBright)){

tmpUbright

= (num - throMid) / (throBright - throMid);

}else{

tmpUbright = 1;

}

return tmpUbright;}

3、根据前面公式,遍历整个源图像,计算出新图像的所有像素值。 for(i=0; i<width; i++){

for(j=0;j<height; j++){

s1 = cvGet2D(&src, i, j);

Udark

= getUdark(s1.val[0]);

Umid

= getUmid(s1.val[0]);

Ubright = getUbright(s1.val[0]);

s1.val[0] = (0 * Udark + 127 * Umid + 255 * Ubright) / (Udark + Umid + Ubright);//

printf("Udark:%lf, Umid:%lf, Ubright:%lf, s1.val[0]%lf\n", Udark, Umid, Ubright, s1.val[0]);

cvSet2D(&src, i, j, s1);

}

} 结果显示

显示的结果如下:

结论分析

原图像、直方图均衡化后图像、模糊集合灰度变换后图像分别对应如下:

可以感觉到,模糊集合灰度变化后的图像看起来效果更好。 具体代码下载: http://download.csdn.net/detail/u011630458/9381775

推荐:OpenCV下的图像对比度增强之完整代码

    // enforce.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "cv.h" #include "highgui.h" #include #includ

简介   本篇主要讲解利用直方图均衡化和使用模糊集合灰度变换方式来优化图片对比度,并直观显示出这两种方式下的优化效果,和优化后图片的直方图分布情况。 直方图显示   开始讲图片对比

相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。