关于二值化函数cvAdaptiveThreshold和cvThreshold以及OSTU

本文对比分析了OpenCV库中的cvAdaptiveThreshold函数及其自适应二值化原理,与固定阈值函数cvThreshold中的Otsu方法。通过实例演示了如何使用cvAdaptiveThreshold进行边缘提取,并解释了窗口大小对结果的影响。同时介绍了Otsu全局阈值算法的实现,包括直方图生成和最大类间方差计算过程。

(1)函数cvAdaptiveThreshold的确可以将灰度图像二值化,但它的主要功能应该是边缘提取,并且参数param1主要是用来控制边缘的类型和粗细的,这些在软件自带的参考手册中均未提及。虽然手册里的阈值计算和判断方法与代码是一致的,但其函数功能说明却给人一种通常意义上的“图像二值化”的印象。

(2)有趣的是,我也留意了一下资料介绍的固定阈值化函数cvThreshold,其实它也有一种自适应阈值方法,那就是OSTU(大津法)!!只需要设定参数thresh_type的值为CV_THRESH_OTSU即可。

(3)前面分析得没问题,自适应二值化就是这样的。这是一种高效实现。自适应二值化计算像素的邻域的平均灰度,来决定二值化的值。如果整个区域几乎是一样灰度的,则无法给出合适的结果了。之所以看起来像边缘检测,是因为窗尺寸设置的小,可以改大一点试一试。
cvAdaptiveThreshold( src, dst, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 21); //窗设置为21
没有万能的二值化方法,具体问题具体分析,自适应二值化对于光照不均的文字,条码等,效果很好。窗口大小选择,考虑被检测物体尺寸。

(4)附:

/*======================================================================*/
/* OTSU global thresholding routine */
/*======================================================================*/

void otsu (IplImage *image)
{
int w = image->width;
int h = image->height;

unsigned char *np; // 图像指针
unsigned char pixel;
int thresholdValue=1; // 阈值
int ihist[256]; // 图像直方图,256个点

int i, j, k; // various counters
int n, n1, n2, gmin, gmax;
double m1, m2, sum, csum, fmax, sb;

// 对直方图置零...
memset(ihist, 0, sizeof(ihist));

gmin=255; gmax=0;
// 生成直方图
for (i = 0; i < h; i++) 
{
np = (unsigned char*)(image->imageData + image->widthStep*i);
for (j = 0; j < w; j++) 
{
pixel = np[j];
ihist[ pixel]++;
if(pixel > gmax) gmax= pixel;
if(pixel < gmin) gmin= pixel;
}
}

// set up everything
sum = csum = 0.0;
n = 0;

for (k = 0; k <= 255; k++) 
{
sum += k * ihist[k]; /* x*f(x) 质量矩*/
n += ihist[k]; /* f(x) 质量 */
}

if (!n) 
{
// if n has no value, there is problems...
//fprintf (stderr, "NOT NORMAL thresholdValue = 160\n");
thresholdValue = 160;
goto L;
}

// do the otsu global thresholding method
fmax = -1.0;
n1 = 0;
for (k = 0; k < 255; k++) 
{
n1 += ihist[k];
if (!n1) { continue; }
n2 = n - n1;
if (n2 == 0) { break; }
csum += k *ihist[k];
m1 = csum / n1;
m2 = (sum - csum) / n2;
sb = n1 * n2 *(m1 - m2) * (m1 - m2);
/* bbg: note: can be optimized. */
if (sb > fmax)
{
fmax = sb;
thresholdValue = k;
}
}

L:
for (i = 0; i < h; i++) 
{
np = (unsigned char*)(image->imageData + image->widthStep*i);
for (j = 0; j < w; j++) 
{
if(np[j] >= thresholdValue)
np[j] = 255;
else np[j] = 0;
}
}
}


 

`cvAdaptiveThreshold` 函数用于对图像进行自适应阈值处理,以下是该函数的具体参数: ```python cvAdaptiveThreshold(const CvArr* src, CvArr* dst, double max_value, int adaptive_method CV_DEFAULT(CV_ADAPTIVE_THRESH_MEAN_C), int threshold_type CV_DEFAULT(CV_THRESH_BINARY), int block_size CV_DEFAULT(3), double param1 CV_DEFAULT(5)) ``` 参数含义如下: - `src`:输入图像,通常为单通道图像(如灰度图)。 - `dst`:输出图像,与输入图像大小类型相同。 - `max_value`:当像素值满足条件时,将被设置的最大值。 - `adaptive_method`:自适应阈值的计算方法,常见取值有: - `CV_ADAPTIVE_THRESH_MEAN_C`:阈值是邻域的平均值减去 `param1`。 - `CV_ADAPTIVE_THRESH_GAUSSIAN_C`:阈值是邻域的高斯加权减去 `param1`。 - `threshold_type`:阈值类型,常见取值有: - `CV_THRESH_BINARY`:二值化类型,大于阈值的像素设为 `max_value`,小于的设为 0。 - `CV_THRESH_BINARY_INV`:与 `CV_THRESH_BINARY` 相反,大于阈值的像素设为 0,小于的设为 `max_value`。 - `block_size`:邻域大小,必须为奇数,用于计算自适应阈值。 - `param1`:从计算出的邻域平均值或加权中减去的常数。 ### 参数选择方法 - **`max_value`**:通常根据图像像素值范围选择,对于 8 位图像,一般设为 255。 - **`adaptive_method`**: - 如果图像光照分布比较均匀,可选择 `CV_ADAPTIVE_THRESH_MEAN_C`。 - 如果图像光照变化较大,`CV_ADAPTIVE_THRESH_GAUSSIAN_C` 可能效果更好,因为它考虑了邻域内像素的权重。 - **`threshold_type`**:根据具体需求选择,如果希望前景像素为白色,背景为黑色,选择 `CV_THRESH_BINARY`;反之选择 `CV_THRESH_BINARY_INV`。 - **`block_size`**:该参数影响局部阈值的计算范围。如果图像细节丰富,可选择较小的值,如 3、5 或 7;如果图像噪声较多或光照变化缓慢,可选择较大的值,如 11、15 等,但不宜过大,否则会使局部阈值失去意义。 - **`param1`**:需要根据图像的具体情况进行调整。如果图像噪声较多,可适当增大该值以减少噪声的影响;如果图像细节丢失严重,可适当减小该值。 ```python import cv2 # 读取图像 image = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE) # 进行自适应阈值处理 adaptive_threshold_image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) # 显示结果 cv2.imshow('Adaptive Threshold', adaptive_threshold_image) cv2.waitKey(0) cv2.destroyAllWindows() ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值