限制对⽐度⾃适应直⽅图均衡化
⼀、⾃适应直⽅图均衡化(Adaptive histgram equalization/AHE)
1.简述
⾃适应直⽅图均衡化(AHE)⽤来提升图像的对⽐度的⼀种计算机图像处理技术。和普通的直⽅图均衡算法不同,AHE算法通过计算图像的局部直⽅图,然后重新分布亮度来来改变图像对⽐度。因此,该算法更适合于改进图像的局部对⽐度以及获得更多的图像细节。
不过,AHE有过度放⼤图像中相同区域的噪⾳的问题,另外⼀种⾃适应的直⽅图均衡算法即限制对⽐度直⽅图均衡(CLAHE)算法能有限的限制这种不利的放⼤。
2. 算法的解释
普通的直⽅图均衡算法对于整幅图像的像素使⽤相同的直⽅图变换,对于那些像素值分布⽐较均衡的图像来说,算法的效果很好。然后,如果图像中包括明显⽐图像其它区域暗或者亮的部分,在这些部分的对⽐度将得不到有效的增强。
AHE算法通过对局部区域执⾏响应的直⽅图均衡来改变上述问题。该算法⾸先被开发出来适⽤于改进航
天器驾驶舱的显⽰效果。其最简单的形式,就是每个像素通过其周边⼀个矩形范围内的像素的直⽅图进⾏均衡化。均衡的⽅式则完全同普通的均衡化算法:变换函数同像素周边的累积直⽅图函数(CDF)成⽐例。
图像边缘的像素需要特殊处理,因为边缘像素的领域不完全在图像内部。这个通过镜像图像边缘的⾏像素或列像素来解决。直接复制边缘的像素进⾏扩充是不合适的。因为这会导致带有剑锋的领域直⽅图。
3. AHE的属性
领域的⼤⼩是该⽅法的⼀个参数。领域⼩,对⽐度得到增强,领域⼤,则对⽐度降低。
当某个区域包含的像素值⾮常相似,其直⽅图就会尖状化,此时直⽅图的变换函数会将⼀个很窄范围内的像素映射到整个像素范围。这将使得某些平坦区域中的少量噪⾳经AHE处理后过度放⼤。
⼆、限制对⽐度⾃适应直⽅图均衡(Contrast Limited Adaptive histgram equalization/CLAHE)
  1.简述
CLAHE同普通的⾃适应直⽅图均衡不同的地⽅主要是其对⽐度限幅。这个特性也可以应⽤到全局直⽅
图均衡化中,即构成所谓的限制对⽐度直⽅图均衡(CLHE),但这在实际中很少使⽤。在CLAHE中,对于每个⼩区域都必须使⽤对⽐度限幅。CLAHE主要是⽤来克服AHE 的过度放⼤噪⾳的问题。
这主要是通过限制AHE算法的对⽐提⾼程度来达到的。在指定的像素值周边的对⽐度放⼤主要是由变换函数的斜度决定的。这个斜度和领域的累积直⽅图的斜度成⽐例。CLAHE通过在计算CDF前⽤预先定义的阈值来裁剪直⽅图以达到限制放⼤幅度的⽬的。这限制了CDF的斜度因此,也限制了变换函数的斜度。直⽅图被裁剪的值,也就是所谓的裁剪限幅,取决于直⽅图的分布因此也取决于领域⼤⼩的取值。
通常,直接忽略掉那些超出直⽅图裁剪限幅的部分是不好的,⽽应该将这些裁剪掉的部分均匀的分布到直⽅图的其他部分。如下图所⽰。
这个重分布的过程可能会导致那些倍裁剪掉的部分由重新超过了裁剪值(如上图的绿⾊部分所⽰)。如果这不是所希望的,可以不带使⽤重复不的过程指导这个超出的部分已经变得微不⾜道了。
2. 通过插值加快计算速度
如上所述的直接的⾃适应直⽅图,不管是否带有对⽐度限制,都需要对图像中的每个像素计算器领域直⽅图以及对应的变换函数,这使得算法及其耗时。
⽽插值使得上述算法效率上有极⼤的提升,并且质量上没有下降。⾸先,将图像均匀分成等份矩形⼤⼩,如下图的右侧部分所⽰(8⾏8列64个块是常⽤的选择)。然后计算个块的直⽅图、CDF以及对应的变换函数。这个变换函数对于块的中⼼像素(下图左侧部分的⿊⾊⼩⽅块)是完全符合原始定义的。⽽其他的像素通过哪些于其临近的四个块的变换函数插值获取。位于图中蓝⾊阴影部分的像素采⽤双线性查插值,⽽位于便于边缘的(绿⾊阴影)部分采⽤线性插值,⾓点处(红⾊阴影处)直接使⽤块所在的变换函数。
这样的过程极⼤的降低了变换函数需要计算的次数,只是增加了⼀些双线性插值的计算量。
clahe.h
//*****************************************************************************
// Contrast Limited Adaptive Histogram Equalization (CLAHE) for OpenCV
//-----------------------------------------------------------------------------
// Original CLAHE implementation by Karel Zuiderveld, karel@cv.ruu.nl
// Original CLAHE implementation by Karel Zuiderveld, karel@cv.ruu.nl
// in "Graphics Gems IV", Academic Press, 1994.
//-----------------------------------------------------------------------------
// Converted to OpenCV format by Toby Breckon, toby.breckon@cranfield.ac.uk
// Copyright (c) 2009 School of Engineering, Cranfield University
// License : LGPL - /licenses/lgpl.html
//-----------------------------------------------------------------------------
// Improved by Shervin Emami on 17th Nov 2010, ami@gmail
// /
//*****************************************************************************
#include <cv.h>      // open cv general include file
// *****************************************************************************
/
/ CLAHE input/output range flag definitions
#define CV_CLAHE_RANGE_FULL 0
#define CV_CLAHE_RANGE_INPUT 1
// *****************************************************************************
// cvAdaptEqualize(src, dst, xdivs, ydivs, bins)
//
// src - pointer to source image (must be single channel 8-bit)
// dst - pointer to destination image (must be single channel 8-bit)
// xdivs - number of cell divisions to use in vertical (x) direction (MIN=2 MAX = 16)
// ydivs - number of cell divisions to use in vertical (y) direction (MIN=2 MAX = 16)
// bins - number of histogram bins to use per division
局部直方图均衡化/
/ range - either of CV_CLAHE_RANGE_INPUT or CV_CLAHE_RANGE_FULL to limit the output
//        pixel range to the min/max range of the input image or the full range of the
//        pixel depth (8-bit in this case)
void cvAdaptEqualize(IplImage *src, IplImage *dst,
unsigned int xdivs, unsigned int ydivs, unsigned int bins, int range);
// cvCLAdaptEqualize(src, dst, xdivs, ydivs, bins, limit)
//
// src - pointer to source image (must be single channel 8-bit)
// dst - pointer to destination image (must be single channel 8-bit)
// xdivs - number of cell divisions to use in vertical (x) direction (MIN=2 MAX = 16)
// ydivs - number of cell divisions to use in vertical (y) direction (MIN=2 MAX = 16)
/
/ bins - number of histogram bins to use per division
// limit - contrast limit for localised changes in contrast
// range - either of CV_CLAHE_RANGE_INPUT or CV_CLAHE_RANGE_FULL to limit the output
//        pixel range to the min/max range of the input image or the full range of the
//        pixel depth (8-bit in this case)
void cvCLAdaptEqualize(IplImage *src, IplImage *dst,
unsigned int xdivs, unsigned int ydivs, unsigned int bins, float limit,
int range);
// *****************************************************************************
/*
redefine : CV_ERROR_LOCAL macro unconditionally raises error with passed code and message.  After raising error, control will be transferred to the exit label.
*/
#undef CV_ERROR
#define CV_ERROR( Code, Msg )                                      \
{                                                                  \
cvError( (Code), "CLAHE code", Msg, __FILE__, __LINE__ );      \
exit(1);                                                          \
exit(1);                                                          \
}
// *****************************************************************************
clahe.cpp
//*****************************************************************************
/
/ Contrast Limited Adaptive Histogram Equalization (CLAHE) for OpenCV
//-----------------------------------------------------------------------------
// Original CLAHE implementation by Karel Zuiderveld, karel@cv.ruu.nl
// in "Graphics Gems IV", Academic Press, 1994.
//-----------------------------------------------------------------------------
// Converted to OpenCV format by Toby Breckon, toby.breckon@cranfield.ac.uk
// Copyright (c) 2009 School of Engineering, Cranfield University
// License : LGPL - /licenses/lgpl.html
//-----------------------------------------------------------------------------
// Improved by Shervin Emami on 17th Nov 2010, ami@gmail
// /
/
/*****************************************************************************
#include <cv.h>      // open cv general include file
#include "clahe.h"  // opencv CLAHE include file
#include <stdio.h>
#include <stdlib.h>
// *****************************************************************************
// type defs. for Graphic Gemms Code - see later
#define BYTE_IMAGE
#ifdef BYTE_IMAGE
typedef unsigned char kz_pixel_t;        /* for 8 bit-per-pixel images */
#define uiNR_OF_GREY (256)
#else
typedef unsigned short kz_pixel_t;      /* for 12 bit-per-pixel images (default) */
# define uiNR_OF_GREY (4096)
#endif
/************* Prototype of Graphic Gemms CLAHE function. *********************/
static int CLAHE(kz_pixel_t* pImage, unsigned int uiXRes,
unsigned int uiYRes, kz_pixel_t Min,
kz_pixel_t Max, unsigned int uiNrX, unsigned int uiNrY,
unsigned int uiNrBins, float fCliplimit);
// *****************************************************************************
// General Notes:
/
/
// The number of "effective" greylevels in the output image is set by bins; selecting
// a small value (eg. 128) speeds up processing and still produce an output image of
// good quality. The output image will have the same minimum and maximum value as the input // image. A clip limit smaller than 1 (?? is this correct ) results in
//  standard (non-contrast limited) AHE.
// cvAdaptEqualize(src, dst, xdivs, ydivs, bins)
//
// perform adaptive histogram equalization (AHE)
//
//
// src - pointer to source image (must be single channel 8-bit)
// dst - pointer to destination image (must be single channel 8-bit)
// xdivs - number of cell divisions to use in vertical (x) direction (MIN=2 MAX = 16)
// ydivs - number of cell divisions to use in vertical (y) direction (MIN=2 MAX = 16)
// bins - number of histogram bins to use per division
// range - either of CV_CLAHE_RANGE_INPUT or CV_CLAHE_RANGE_FULL to limit the output //        pixel range to the min/max range of the input image or the full range of the
//        pixel depth (8-bit in this case)
void cvAdaptEqualize(IplImage *src, IplImage *dst,
unsigned int xdivs, unsigned int ydivs, unsigned int bins, int range)
{
// call CLAHE with negative limit (as flag value) to perform AHE (no limits)
cvCLAdaptEqualize(src, dst, xdivs, ydivs, bins, -1.0, range);
}
// cvCLAdaptEqualize(src, dst, xdivs, ydivs, bins, limit)
//
// perform contrast limited adaptive histogram equalization (CLAHE)
//
// src - pointer to source image (must be single channel 8-bit)
// dst - pointer to destination image (must be single channel 8-bit)
// xdivs - number of cell divisions to use in vertical (x) direction (MIN=2 MAX = 16)
// ydivs - number of cell divisions to use in vertical (y) direction (MIN=2 MAX = 16)
// bins - number of histogram bins to use per division (MIN=2 MAX = 256)
// limit - contrast limit for localised changes in contrast
/
/ (limit >= 0 gives standard AHE without contrast limiting)
// range - either of CV_CLAHE_RANGE_INPUT or CV_CLAHE_RANGE_FULL to limit the output //        pixel range to the min/max range of the input image or the full range of the
//        pixel depth (8-bit in this case)
void cvCLAdaptEqualize(IplImage *src, IplImage *dst,
unsigned int xdivs, unsigned int ydivs, unsigned int bins,
float limit, int range)
{
double min_val, max_val;
unsigned char min, max;
// CV_FUNCNAME( "cvCLAdaptEquualize" );
// __BEGIN__;
// check the inputs to the function
int type;
if ((src == NULL) || (dst == NULL))
CV_ERROR( CV_StsUnsupportedFormat, "NULL value passed as image to function" );
CV_CALL( type = cvGetElemType( src ));
if( type != CV_8UC1 )
CV_ERROR( CV_StsUnsupportedFormat, "Only 8uC1 images are supported" );
CV_CALL( type = cvGetElemType( src ));
if( type != CV_8UC1 )
CV_ERROR( CV_StsUnsupportedFormat, "Only 8uC1 images are supported" );
//if( !CV_ARE_SIZES_EQ( src, dst )) // Modified by Shervin Emami, 17Nov2010.
if (src->width != dst->width || src->height != dst->height)
CV_ERROR( CV_StsUnmatchedSizes, "src and dst images must be equal sizes" );
if (((xdivs < 2) || (xdivs > 16)) || ((ydivs < 2) || (ydivs > 16)))
CV_ERROR( CV_StsBadFlag, "xdivs and ydivs must in range (MIN=2 MAX = 16)" );
CV_ERROR( CV_StsBadFlag, "xdivs and ydivs must in range (MIN=2 MAX = 16)" );
if ((bins < 2) || (bins > 256))
CV_ERROR( CV_StsBadFlag, "bins must in range (MIN=2 MAX = 256)" );
// copy src to dst for in-place CLAHE.
cvCopy(src, dst);
// If the dimensions of the image are not a multiple of the xdivs and ydivs, then enlarge the image to be a correct size and then shrink the image. // Also make sure the image is aligned to 8 pixels width, so that OpenCV won't add extra padding to the image.
// Added by Shervin Emami, 17Nov2010.
int enlarged = 0;
int origW = dst->width;
int origH = dst->height;
IplImage *tmpDst = 0;
if ((dst->width & (8-1)) || (dst->height & (8-1)) || (dst->width % xdivs) || (dst->height % ydivs)) {
int newW = ((dst->width + 8-1) & -8); // Align to 8 pixels, so that widthStep hopefully equals width.
newW = ((newW + xdivs-1) & -xdivs);  // Also align for CLAHE.
int newH = ((dst->height + ydivs-1) & -ydivs);
//std::cout << "w=" << dst->width << ", h=" << dst->height << ". new w = " << newW << ", h = " << newH << std::endl;
IplImage *enlargedDst = cvCreateImage(cvSize(newW, newH), dst->depth, dst->nChannels);
cvResize(dst, enlargedDst, CV_INTER_CUBIC);
//cvReleaseImage(&dst);
tmpDst = dst;
dst = enlargedDst; // Use the enlarged image instead of the original dst image.
enlarged = 1; // signal that we need to shrink later!
}
// Check if OpenCV adds padding bytes on each row. Added by Shervin Emami, 17Nov2010.
if (dst->width != dst->widthStep)
CV_ERROR( CV_StsBadFlag, "dst->widthStep should be the same as dst->width. The IplImage has padding, so use a larger image." );
// check number of xdivs and ydivs is a multiple of image dimensions
if (dst->width % xdivs)
CV_ERROR( CV_StsBadFlag, "xdiv must be an integer multiple of image width " );
if (dst->height % ydivs)
CV_ERROR( CV_StsBadFlag, "ydiv must be an integer multiple of image height " );
// get the min and max values of the image
if (range == CV_CLAHE_RANGE_INPUT) {
cvMinMaxLoc(dst, &min_val, &max_val);
min = (unsigned char) min_val;
max = (unsigned char) max_val;
} else {
min = 0;
max = 255;
}
// call CLHAHE for in-place CLAHE
//int rcode =
CLAHE((kz_pixel_t*) (dst->imageData), (unsigned int) dst->width, (unsigned int)
dst->height, (kz_pixel_t) min, (kz_pixel_t) max, (unsigned int) xdivs, (unsigned int) ydivs,
(unsigned int) bins, (float) limit);
//printf("RCODE %i\n", rcode);
// If the dst image was enlarged to fit the alignment, then shrink it back now.
// Added by Shervin Emami, 17Nov2010.
if (enlarged) {
//std::cout << "w=" << dst->width << ", h=" << dst->height << ". orig w=" << origW << ", h=" << origH << std::endl;
cvResize(dst, tmpDst, CV_INTER_CUBIC); // Shrink the enlarged image back into the original dst image.
cvReleaseImage(&dst); // Free the enlarged image.
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。