bernsen算法的中心思想:
先人为设定两个值S与TT(Bemsen最初设S为15,TT设为128),计算以图像中任意像素尸为中心的大小为k×k窗口内的所有像素的最大值M与最小值N,两者的均值T,如果朋M-N大于S,则当前P的阈值为T;若小于S,则表示该窗口所在区域灰度级灰度级差别较小,那么窗口在目标区或在背景区,再判断T与TT的关系,若T>TT则当前点灰度值为255,否则当前点灰度值为0。
改进的bernsen算法:
1.消除个别灰度特异点,设采用的阈值为T1。
T1的取值满足:
A为图像的总像素个数。
代码:
int getThreshBernsen(IplImage *src) { uchar num[256]; int w = src->width; int h = src->height; int s = src->widthStep; int T1 = 0; int pix = 0; int a = w * h; memset(num, 0, 256); //统计灰度值的个数 for(int i=0; i<=255; i++) { for(int j=1; j<= h; j++) { for(int m=1; m<= w; m++) { if(((uchar*)src->imageData + j*s)[m] == i) { num[i] = num[i] + 1; } } } } for(int i=255; i>=0; i--) { pix = pix + num[i]; if(pix >= (0.1*a)) { T1 = i; break; } } cout << T1 << endl; return T1; }
2 计算每一个点的阈值
IplImage *T2 = cvCreateImage(cvGetSize(src), 8, 1); memset((uchar*)T2->imageData, 0, T2->height*T2->widthStep); IplImage *T3 = cvCreateImage(cvGetSize(src), 8, 1); memset((uchar*)T3->imageData, 0, T3->height*T3->widthStep); for(int i = BOX_SIFT; i<T2->height - BOX_SIFT; i++) { for(int j=BOX_SIFT; j<T2->width - BOX_SIFT; j++) { CvRect rect; rect.x = j - BOX_SIFT; rect.y = i - BOX_SIFT; rect.height = BOX_SCALE; rect.width = BOX_SCALE; int max_pix = getMaxPix(src, rect); int min_pix = getMinPix(src, rect); ((uchar *)T2->imageData + i*T2->widthStep)[j] = (min_pix + max_pix) * 0.5; ((uchar *)T3->imageData + i*T2->widthStep)[j] = (min_pix + max_pix); } }IplImage *T4 = cvCreateImage(cvGetSize(src), 8, 1); memset((uchar*)T4->imageData, 0, T4->height*T4->widthStep); for(int i = BOX_SIFT; i<T4->height - BOX_SIFT; i++) { for(int j=BOX_SIFT; j<T4->width - BOX_SIFT; j++) { CvRect rect; rect.x = j - BOX_SIFT; rect.y = i - BOX_SIFT; rect.height = BOX_SCALE; rect.width = BOX_SCALE; int mean = getMean(T2, rect); ((uchar *)T4->imageData + i*T4->widthStep)[j] = mean; } }
3.逐点二值化
伪代码:
if f(x,y) > (1+a)*T1; b(x,y) = 255;else if f(x,y) < (1-a)*T1; b(x,y) = 0;else if T3(x,y) > a*T1 if f(x,y) < T4(x,y) b(x,y) = 0 else b(x,y) = 255 else if f(x,y) < T3(x,y) b(x,y) = 0 else b(x,y) = 255
联系客服