使用积分图的自适应二值化算法

简介: 使用积分图的自适应二值化算法


使用积分图的自适应二值化算法

Adaptive Thresholding Using the Integral Image

对图像进行阈值处理的目的是将像素划分为 "暗 "或 “亮”。

自适应阈值处理是一种阈值处理形式,它考虑到了光照的空间变化,对图像中的光照变化具有更强的鲁棒性。

积分图像

参考:积分图像

积分图算法是一种快速计算图像区域和以及图像区域平方和的算法。

核心思想就是对每一个图像建立起自己的积分图查找表,在图像处理的阶段就可以根据预先建立积分图查找表直接查找从而实现对均值卷积的线性时间计算。

一张图像就是一个矩形,这个矩形中每个像素点的积分值,就是以图像左上角像素点为左上角顶点,以该像素点为右下角顶点的矩形中包含的所有元素之和。

通常不会对每一个像素点都重新计算矩形区域包含的所有元素值之和,而是利用相邻点的积分值实现快速计算。

I ( x , y ) = I ( x − 1 , y ) + I ( x , y − 1 ) − I ( x − 1 , y − 1 ) + p i x e l ( x , y ) I(x,y) = I(x-1,y) + I(x,y-1) -I(x-1,y-1)+ pixel(x,y)I(x,y)=I(x1,y)+I(x,y1)I(x1,y1)+pixel(x,y)

( x , y ) (x,y)(x,y)的积分值可以使用点( x − 1 , y ) (x-1,y)(x1,y)与点( x , y − 1 ) (x,y-1)(x,y1)的积分值之和,减去重叠区域,然后再加上点( x , y ) (x,y)(x,y)的像素值得到。

伪代码

自适应二值化

基本思想:取一个以目标点为中心的方块,如果目标点的像素小于这个方块像素平均值的T % T\%T%,就将目标点划分为 "暗 “,否则划分为"亮”。

T = 1 − t T= 1-tT=1t

自适应二值化可以配置的参数有两个:

  1. 选取方块的边长s ss
  2. 阈值t tt

经验值:s ss取1/8 的图像宽度,t tt取15

使用积分图可以加快选取方块平均值的计算

区域D像素和的快速计算公式:

∑ x = x 1 x 2 ∑ y = y 1 y 2 f ( x , y ) = I ( x 2 , y 2 ) − I ( x 2 , y 1 − 1 ) − I ( x 1 − 1 , y 2 ) + I ( x 1 − 1 , y 1 − 1 ) \sum_{x=x_1}^{x_2}\sum_{y=y_1}^{y_2} f(x,y) = I(x_2,y_2)-I(x_2,y_1-1)-I(x_1-1,y_2)+I(x_1-1,y_1-1)x=x1x2y=y1y2f(x,y)=I(x2,y2)I(x2,y11)I(x11,y2)+I(x11,y11)

D = ( A + B + C + D ) − ( A + B ) − ( A + C ) + A D = (A+B+C+D) -(A+B)-(A+C) + AD=(A+B+C+D)(A+B)(A+C)+A

伪代码

代码实现

#include <iostream>
#include <stdlib.h>
using namespace std;
/** 使用积分图像的自适应二值化
* @param in   输入图像
* @param in_w   输入图像的宽度
* @param in_h   输入图像的高度
* @param at_s   选取方块的边长
* @param at_t   阈值
* @param out    二值化后的结果
*/
void AdaptiveThreshold(unsigned char* in, unsigned int in_w, unsigned int in_h, unsigned int at_s, unsigned char at_t, unsigned char* out) {
  unsigned int* int_data = (unsigned int*)malloc(sizeof(unsigned int) * in_w * in_h);
  unsigned int sum = 0;
  unsigned int x1, x2, y1, y2;
  unsigned int count;
  // Calc Integral Image
  for (unsigned int x = 0; x < in_w; x++) {
    sum = 0;
    for (unsigned int y = 0; y < in_h; y++) {
      sum += *(in + y * in_w + x);
      if (x == 0) {
        *(int_data + y * in_w + x) = sum;
      }
      else {
        *(int_data + y * in_w + x) = *(int_data + y * in_w + x - 1) + sum;
      }
    }
  }
  // Threshold
  for (unsigned int x = 0; x < in_w; x++) {
    for (unsigned int y = 0; y < in_h; y++) {
      x1 = x <= at_s / 2 ? 0 : (x - at_s / 2);
            x2 = x + at_s / 2; if (x2 > in_w - 1) x2 = in_w - 1;
      
      y1 = y <= at_s/2 ? 0: (y - at_s / 2);
      y2 = y + at_s / 2; if (y2 > in_h - 1) y2 = in_h - 1;
      count = (x2 - x1 +1 ) * (y2 - y1 + 1);
      if (x1 == 0 && y1 == 0) {
        sum = *(int_data + y2 * in_w + x2);
      }
      else if (x1 == 0) {
        sum = *(int_data + y2 * in_w + x2) - *(int_data + (y1 - 1) * in_w + x2);
      }
      else if (y1 == 0) {
        sum = *(int_data + y2 * in_w + x2) - *(int_data + y2 * in_w + x1 - 1);
      }
      else {
        sum = *(int_data + y2 * in_w + x2) - *(int_data + (y1 - 1) * in_w + x2) - *(int_data + y2 * in_w + x1 - 1) + *(int_data + (y1 - 1) * in_w + x1 - 1);
      }
    
      if (*(in + y * in_w + x) * count <= (sum * (100 - at_t) / 100)) {
        *(out + y * in_w + x) = 0;
      }
      else {
        *(out + y * in_w + x) = 255;
      }
    }
  }
  free(int_data);
  int_data = NULL;
}

应用

#include <iostream>
#include <stdlib.h>
#include <opencv2/core.hpp> 
#include <opencv2/highgui.hpp> 
#include <opencv2/imgproc.hpp>
int main()
{
    cv::Mat img = cv::imread("F:\\OpencvTemplate\\img\\2.png");
  cv::Mat gray;
  cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
  cv::Mat out = cv::Mat::zeros(gray.size(), CV_8UC1);
  AdaptiveThreshold((uint8_t*)(gray.data), img.cols, img.rows, 32, 15, (uint8_t*)(out.data));
    cv::namedWindow("threshold", cv::WINDOW_GUI_EXPANDED);
    cv::resizeWindow("threshold", img.cols / 3, img.rows / 3);
    cv::imshow("threshold", out);
    cv::waitKey(0);
    return 0;
}

论文和代码

https://download.csdn.net/download/first_bug/88407474

相关文章
|
23天前
|
算法 计算机视觉
图像处理之积分图应用四(基于局部均值的图像二值化算法)
图像处理之积分图应用四(基于局部均值的图像二值化算法)
92 0
|
23天前
|
监控 算法 图计算
图像处理之积分图应用三(基于NCC快速相似度匹配算法)
图像处理之积分图应用三(基于NCC快速相似度匹配算法)
20 0
|
19天前
|
算法 调度 决策智能
基于自适应遗传算法的车间调度matlab仿真,可以任意调整工件数和机器数,输出甘特图
这是一个使用MATLAB2022a实现的自适应遗传算法解决车间调度问题的程序,能调整工件数和机器数,输出甘特图和适应度收敛曲线。程序通过编码初始化、适应度函数、遗传操作(选择、交叉、变异)及自适应机制进行优化,目标如最小化完工时间。算法在迭代过程中动态调整参数,以提升搜索效率和全局优化。
|
20天前
|
算法
基于ADM自适应增量调制算法的matlab性能仿真
该文主要探讨基于MATLAB的ADM自适应增量调制算法仿真,对比ADM与DM算法。通过图表展示调制与解调效果,核心程序包括输入输出比较及SNR分析。ADM算法根据信号斜率动态调整量化步长,以适应信号变化。在MATLAB中实现ADM涉及定义输入信号、初始化参数、执行算法逻辑及性能评估。
|
23天前
|
资源调度 算法 计算机视觉
图像处理之积分图应用二(快速边缘保留滤波算法)
图像处理之积分图应用二(快速边缘保留滤波算法)
12 0
|
23天前
|
算法 BI 计算机视觉
图像处理之积分图应用一(半径无关的快速模糊算法)
图像处理之积分图应用一(半径无关的快速模糊算法)
14 0
|
5天前
|
机器学习/深度学习 自然语言处理 算法
m基于深度学习的OFDM+QPSK链路信道估计和均衡算法误码率matlab仿真,对比LS,MMSE及LMMSE传统算法
**摘要:** 升级版MATLAB仿真对比了深度学习与LS、MMSE、LMMSE的OFDM信道估计算法,新增自动样本生成、复杂度分析及抗频偏性能评估。深度学习在无线通信中,尤其在OFDM的信道估计问题上展现潜力,解决了传统方法的局限。程序涉及信道估计器设计,深度学习模型通过学习导频信息估计信道响应,适应频域变化。核心代码展示了信号处理流程,包括编码、调制、信道模拟、降噪、信道估计和解调。
26 8
|
7天前
|
算法
基于GA遗传优化的混合发电系统优化配置算法matlab仿真
**摘要:** 该研究利用遗传算法(GA)对混合发电系统进行优化配置,旨在最小化风能、太阳能及电池储能的成本并提升系统性能。MATLAB 2022a用于实现这一算法。仿真结果展示了一系列图表,包括总成本随代数变化、最佳适应度随代数变化,以及不同数据的分布情况,如负荷、风速、太阳辐射、弃电、缺电和电池状态等。此外,代码示例展示了如何运用GA求解,并绘制了发电单元的功率输出和年变化。该系统原理基于GA的自然选择和遗传原理,通过染色体编码、初始种群生成、适应度函数、选择、交叉和变异操作来寻找最优容量配置,以平衡成本、效率和可靠性。
|
8天前
|
机器学习/深度学习 算法
基于鲸鱼优化的knn分类特征选择算法matlab仿真
**基于WOA的KNN特征选择算法摘要** 该研究提出了一种融合鲸鱼优化算法(WOA)与K近邻(KNN)分类器的特征选择方法,旨在提升KNN的分类精度。在MATLAB2022a中实现,WOA负责优化特征子集,通过模拟鲸鱼捕食行为的螺旋式和包围策略搜索最佳特征。KNN则用于评估特征子集的性能。算法流程包括WOA参数初始化、特征二进制编码、适应度函数定义(以分类准确率为基准)、WOA迭代搜索及最优解输出。该方法有效地结合了启发式搜索与机器学习,优化特征选择,提高分类性能。
|
1天前
|
算法 安全 数据库
基于结点电压法的配电网状态估计算法matlab仿真
**摘要** 该程序实现了基于结点电压法的配电网状态估计算法,旨在提升数据的准确性和可靠性。在MATLAB2022a中运行,显示了状态估计过程中的电压和相位估计值,以及误差随迭代变化的图表。算法通过迭代计算雅可比矩阵,结合基尔霍夫定律解决线性方程组,估算网络节点电压。状态估计过程中应用了高斯-牛顿或莱文贝格-马夸尔特法,处理量测数据并考虑约束条件,以提高估计精度。程序结果以图形形式展示电压幅值和角度估计的比较,以及估计误差的演变,体现了算法在处理配电网状态估计问题的有效性。