直方图均衡化
2017-11-27 21:52
148 查看
转自http://blog.csdn.net/jaych/article/details/49133493#comments
![](https://img-blog.csdn.net/20160203202118687?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
可以看到左上角的图像灰度比较集中,经过直方图均衡化之后,右下角的图像的灰度就被拉伸。
其原理是将图像中的灰度值根据其概率分布在0-255的区间。
转换后的灰度值为:
![](https://img-blog.csdn.net/20160203203856485?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
其中,sk是转变后的灰度值;
rk是输入的灰度值,
nj是灰度值为 j 的像素个数;
k是当前的灰度值,取值范围0到L-1(L通常为256)。
L表示灰度值可取的个数,如8bit的图像可以表示的灰度值有256,L=256.
![](https://img-blog.csdn.net/20160203204403402?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这里我们可以得到下图所示的表,其中,L-1=7;Pr=像素个数/25;
![](https://img-blog.csdn.net/20160203204913504?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
根据转换后的灰度值,替换原先的像素值,图像变成:
![](https://img-blog.csdn.net/20160203204843331?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
[cpp]
view plain
copy
print?
<span style="font-size:14px;">bool getHist(unsigned char *pImgData, unsigned char *pHistData,int height,int width)
{ // 此处需要对输入的指针进行非空判断,此处略。
int grayLvl[256]={0};
float fP[256];
int i;
int sum = height*width; //计算总像素个数
for(i=0 ; i < sum ;i++) //统计各个灰度值的像素点个数
{
grayLvl[pImgData[i]]++;
}
for(i=0; i < 256;i++) //计算每个灰度值的比重
{
fP[i]=(float)grayLvl[i]/(float)sum;
}
for(i=1; i < 256;i++)
{
fP[i]=fP[i-1]+fP[i];
}
for(i=0; i <m_ByteOfData;i++) //均衡化
{
<span style="white-space: pre;"> </span>pHistData[i]=(unsigned char)(fP[pImgData[i]]*255.0+0.5);// 加上0.5是为了能够四舍五入取值。
}
return true;
}</span><span style="font-size: 18px;">
</span>
[cpp]
view plain
copy
print?
<span style="font-size:14px;">void Java_com_example_imageprocess_MainActivity_getHist(JNIEnv* env,jobject thiz,jbyteArray imgData, jbyteArray histData, jlong size)
{
jint* graylvl=(jint*)malloc(256*sizeof(jint));
jfloat* pb=(jfloat*)malloc(256*sizeof(jfloat));
unsigned char* grayHist=(unsigned char*)malloc(256*sizeof(unsigned char));
unsigned char *imgData_buf=(*env)->GetByteArrayElements(env,imgData,0); //获取jni数组
unsigned char *histData_buf = (*env)->GetByteArrayElements(env,histData, NULL);
int i;
unsigned char index=0;
memset(graylvl,0,256*sizeof(jint));
for(i=0;i<size;i++)
{
graylvl[imgData_buf[i]]++;
}
for(i=0;i<256;i++)
{
pb[i]=(jfloat)graylvl[i]/(jfloat)size;
}
grayHist[0]=(unsigned char)(pb[0]*255.0+0.5);
for(i=1;i<256;i++)
{
pb[i]=pb[i-1]+pb[i];
grayHist[i]=(unsigned char)(pb[i]*255.0+0.5);
}
for(i=0;i<size;i++)
{
histData_buf[i]=grayHist[imgData_buf[i]];
}
//save the data from histData_buf to histData
(*env)->SetByteArrayRegion(env,histData, 0, size,histData_buf);
free(graylvl);
free(pb);
free(grayHist);
}</span>
[cpp]
view plain
copy
print?
<span style="font-size:14px;"><span style="font-size:18px;">void Java_com_example_imageprocess_MainActivity_getHist(JNIEnv* env,jobject thiz,jbyteArray imgData, jbyteArray histData, jlong size)
{
jint* graylvl=(jint*)malloc(256*sizeof(jint));
jint* graylvlPtr=graylvl;
unsigned int* pb=(unsigned int*)malloc(256*sizeof(unsigned int));
unsigned int *pbPtr=pb;
unsigned char* grayHist=(unsigned char*)malloc(256*sizeof(unsigned char));
unsigned char *grayHistPtr=grayHist+1;
unsigned char *imgData_buf=(*env)->GetByteArrayElements(env,imgData,0);
unsigned char *imgPtr=imgData_buf;
unsigned char *histData_buf = (*env)->GetByteArrayElements(env,histData, NULL);
unsigned char *histPtr=histData_buf;
int i;
unsigned char index=0;
unsigned int temp = (255<<20)/size;
memset(graylvl,0,256*sizeof(jint));
for(i=size;i!=
aa86
0;i--)
{
(*(graylvl+*imgPtr))++;
imgPtr++;
}
for(i=256;i!=0;i--)
{
*pbPtr=*graylvlPtr*temp;
pbPtr++;
graylvlPtr++;
}
grayHist[0]=(pb[0]>>20);
pbPtr=pb+1;
for(i=255;i!=0;i--)
{
*pbPtr=*pbPtr+*(pbPtr-1);
*grayHistPtr=(*pbPtr)>>20;
pbPtr++;
grayHistPtr++;
}
imgPtr=imgData_buf;
for(i=size;i!=0;i--)
{
*histPtr=*(grayHist+*imgPtr);
imgPtr++;
histPtr++;
}
//save the data from histData_buf to histData
(*env)->SetByteArrayRegion(env,histData, 0, size,histData_buf);
free(graylvl);
free(pb);
free(grayHist);
}
</span></span>
未优化的代码运行的时间为11ms,优化后代码运行时间为9ms。
处理的效果如下图所示,C1为未优化代码,C2为优化代码,发现C2运行后的结果存在一定误差,虽然误差较小(误差为1)。
直方图均衡化原理
直方图均衡化的主要思想是直方图统计,在统计之后,根据具体的灰度值及其对应的出现概率,对图片的灰度进行拉伸,使得图像的对比度得到扩展,如下图这张经典的图像所示。可以看到左上角的图像灰度比较集中,经过直方图均衡化之后,右下角的图像的灰度就被拉伸。
其原理是将图像中的灰度值根据其概率分布在0-255的区间。
转换后的灰度值为:
其中,sk是转变后的灰度值;
rk是输入的灰度值,
nj是灰度值为 j 的像素个数;
k是当前的灰度值,取值范围0到L-1(L通常为256)。
L表示灰度值可取的个数,如8bit的图像可以表示的灰度值有256,L=256.
举个例子
下图为具体图像的像素值,已知该图像的灰度值为0~7,现要求对其进行直方图均衡化。这里我们可以得到下图所示的表,其中,L-1=7;Pr=像素个数/25;
根据转换后的灰度值,替换原先的像素值,图像变成:
PC端代码实现
根据以上原理,将其在PC端用程序实现如下:[cpp]
view plain
copy
print?
<span style="font-size:14px;">bool getHist(unsigned char *pImgData, unsigned char *pHistData,int height,int width)
{ // 此处需要对输入的指针进行非空判断,此处略。
int grayLvl[256]={0};
float fP[256];
int i;
int sum = height*width; //计算总像素个数
for(i=0 ; i < sum ;i++) //统计各个灰度值的像素点个数
{
grayLvl[pImgData[i]]++;
}
for(i=0; i < 256;i++) //计算每个灰度值的比重
{
fP[i]=(float)grayLvl[i]/(float)sum;
}
for(i=1; i < 256;i++)
{
fP[i]=fP[i-1]+fP[i];
}
for(i=0; i <m_ByteOfData;i++) //均衡化
{
<span style="white-space: pre;"> </span>pHistData[i]=(unsigned char)(fP[pImgData[i]]*255.0+0.5);// 加上0.5是为了能够四舍五入取值。
}
return true;
}</span><span style="font-size: 18px;">
</span>
<span style="font-size:14px;">bool getHist(unsigned char *pImgData, unsigned char *pHistData,int height,int width) { // 此处需要对输入的指针进行非空判断,此处略。 int grayLvl[256]={0}; float fP[256]; int i; int sum = height*width; //计算总像素个数 for(i=0 ; i < sum ;i++) //统计各个灰度值的像素点个数 { grayLvl[pImgData[i]]++; } for(i=0; i < 256;i++) //计算每个灰度值的比重 { fP[i]=(float)grayLvl[i]/(float)sum; } for(i=1; i < 256;i++) { fP[i]=fP[i-1]+fP[i]; } for(i=0; i <m_ByteOfData;i++) //均衡化 { <span style="white-space: pre;"> </span>pHistData[i]=(unsigned char)(fP[pImgData[i]]*255.0+0.5);// 加上0.5是为了能够四舍五入取值。 } return true; }</span><span style="font-size: 18px;"> </span>
安卓平台移植
在安卓平台,图像处理的操作由JNI实现,基本与上面的程序一致。具体可参考《【安卓开发】JNI程序开发》[cpp]
view plain
copy
print?
<span style="font-size:14px;">void Java_com_example_imageprocess_MainActivity_getHist(JNIEnv* env,jobject thiz,jbyteArray imgData, jbyteArray histData, jlong size)
{
jint* graylvl=(jint*)malloc(256*sizeof(jint));
jfloat* pb=(jfloat*)malloc(256*sizeof(jfloat));
unsigned char* grayHist=(unsigned char*)malloc(256*sizeof(unsigned char));
unsigned char *imgData_buf=(*env)->GetByteArrayElements(env,imgData,0); //获取jni数组
unsigned char *histData_buf = (*env)->GetByteArrayElements(env,histData, NULL);
int i;
unsigned char index=0;
memset(graylvl,0,256*sizeof(jint));
for(i=0;i<size;i++)
{
graylvl[imgData_buf[i]]++;
}
for(i=0;i<256;i++)
{
pb[i]=(jfloat)graylvl[i]/(jfloat)size;
}
grayHist[0]=(unsigned char)(pb[0]*255.0+0.5);
for(i=1;i<256;i++)
{
pb[i]=pb[i-1]+pb[i];
grayHist[i]=(unsigned char)(pb[i]*255.0+0.5);
}
for(i=0;i<size;i++)
{
histData_buf[i]=grayHist[imgData_buf[i]];
}
//save the data from histData_buf to histData
(*env)->SetByteArrayRegion(env,histData, 0, size,histData_buf);
free(graylvl);
free(pb);
free(grayHist);
}</span>
<span style="font-size:14px;">void Java_com_example_imageprocess_MainActivity_getHist(JNIEnv* env,jobject thiz,jbyteArray imgData, jbyteArray histData, jlong size) { jint* graylvl=(jint*)malloc(256*sizeof(jint)); jfloat* pb=(jfloat*)malloc(256*sizeof(jfloat)); unsigned char* grayHist=(unsigned char*)malloc(256*sizeof(unsigned char)); unsigned char *imgData_buf=(*env)->GetByteArrayElements(env,imgData,0); //获取jni数组 unsigned char *histData_buf = (*env)->GetByteArrayElements(env,histData, NULL); int i; unsigned char index=0; memset(graylvl,0,256*sizeof(jint)); for(i=0;i<size;i++) { graylvl[imgData_buf[i]]++; } for(i=0;i<256;i++) { pb[i]=(jfloat)graylvl[i]/(jfloat)size; } grayHist[0]=(unsigned char)(pb[0]*255.0+0.5); for(i=1;i<256;i++) { pb[i]=pb[i-1]+pb[i]; grayHist[i]=(unsigned char)(pb[i]*255.0+0.5); } for(i=0;i<size;i++) { histData_buf[i]=grayHist[imgData_buf[i]]; } //save the data from histData_buf to histData (*env)->SetByteArrayRegion(env,histData, 0, size,histData_buf); free(graylvl); free(pb); free(grayHist); }</span>
安卓代码优化
这里的优化是将浮点数优化成定点数,有一定的效果。[cpp]
view plain
copy
print?
<span style="font-size:14px;"><span style="font-size:18px;">void Java_com_example_imageprocess_MainActivity_getHist(JNIEnv* env,jobject thiz,jbyteArray imgData, jbyteArray histData, jlong size)
{
jint* graylvl=(jint*)malloc(256*sizeof(jint));
jint* graylvlPtr=graylvl;
unsigned int* pb=(unsigned int*)malloc(256*sizeof(unsigned int));
unsigned int *pbPtr=pb;
unsigned char* grayHist=(unsigned char*)malloc(256*sizeof(unsigned char));
unsigned char *grayHistPtr=grayHist+1;
unsigned char *imgData_buf=(*env)->GetByteArrayElements(env,imgData,0);
unsigned char *imgPtr=imgData_buf;
unsigned char *histData_buf = (*env)->GetByteArrayElements(env,histData, NULL);
unsigned char *histPtr=histData_buf;
int i;
unsigned char index=0;
unsigned int temp = (255<<20)/size;
memset(graylvl,0,256*sizeof(jint));
for(i=size;i!=
aa86
0;i--)
{
(*(graylvl+*imgPtr))++;
imgPtr++;
}
for(i=256;i!=0;i--)
{
*pbPtr=*graylvlPtr*temp;
pbPtr++;
graylvlPtr++;
}
grayHist[0]=(pb[0]>>20);
pbPtr=pb+1;
for(i=255;i!=0;i--)
{
*pbPtr=*pbPtr+*(pbPtr-1);
*grayHistPtr=(*pbPtr)>>20;
pbPtr++;
grayHistPtr++;
}
imgPtr=imgData_buf;
for(i=size;i!=0;i--)
{
*histPtr=*(grayHist+*imgPtr);
imgPtr++;
histPtr++;
}
//save the data from histData_buf to histData
(*env)->SetByteArrayRegion(env,histData, 0, size,histData_buf);
free(graylvl);
free(pb);
free(grayHist);
}
</span></span>
<span style="font-size:14px;"><span style="font-size:18px;">void Java_com_example_imageprocess_MainActivity_getHist(JNIEnv* env,jobject thiz,jbyteArray imgData, jbyteArray histData, jlong size) { jint* graylvl=(jint*)malloc(256*sizeof(jint)); jint* graylvlPtr=graylvl; unsigned int* pb=(unsigned int*)malloc(256*sizeof(unsigned int)); unsigned int *pbPtr=pb; unsigned char* grayHist=(unsigned char*)malloc(256*sizeof(unsigned char)); unsigned char *grayHistPtr=grayHist+1; unsigned char *imgData_buf=(*env)->GetByteArrayElements(env,imgData,0); unsigned char *imgPtr=imgData_buf; unsigned char *histData_buf = (*env)->GetByteArrayElements(env,histData, NULL); unsigned char *histPtr=histData_buf; int i; unsigned char index=0; unsigned int temp = (255<<20)/size; memset(graylvl,0,256*sizeof(jint)); for(i=size;i!=0;i--) { (*(graylvl+*imgPtr))++; imgPtr++; } for(i=256;i!=0;i--) { *pbPtr=*graylvlPtr*temp; pbPtr++; graylvlPtr++; } grayHist[0]=(pb[0]>>20); pbPtr=pb+1; for(i=255;i!=0;i--) { *pbPtr=*pbPtr+*(pbPtr-1); *grayHistPtr=(*pbPtr)>>20; pbPtr++; grayHistPtr++; } imgPtr=imgData_buf; for(i=size;i!=0;i--) { *histPtr=*(grayHist+*imgPtr); imgPtr++; histPtr++; } //save the data from histData_buf to histData (*env)->SetByteArrayRegion(env,histData, 0, size,histData_buf); free(graylvl); free(pb); free(grayHist); } </span></span>
未优化的代码运行的时间为11ms,优化后代码运行时间为9ms。
处理的效果如下图所示,C1为未优化代码,C2为优化代码,发现C2运行后的结果存在一定误差,虽然误差较小(误差为1)。
相关文章推荐
- 数字图像的直方图均衡化(C/C++源代码)
- 直方图均衡化的matlab实现
- 直方图均衡化
- 直方图均衡化(色调均化)(一)
- opencv-直方图均衡化
- 图像直方图均衡化和直方图匹配的理解
- 直方图均衡化(python实现)
- Python OpenCV -- 直方图均衡化(十三)
- 直方图均衡化
- 直方图均衡化(cvEqualizeHist)
- 基于matlab的直方图均衡化代码
- 直方图均衡化
- 图像增强对比度的方法——直方图均衡化
- 直方图均衡化
- 趣谈直方图均衡化和规定化
- 关于图像对比度【3】——直方图均衡化的改进
- cvEqualizeHist() 直方图均衡化(多通道彩图)
- Matlab图像处理转灰度图,绘制直方图,直方图均衡化
- 直方图均衡化
- 直方图均衡化原理