直方图规定化

介绍了一种实现图像直方图匹配的算法,该算法能够通过指定的灰度拉伸点来增强图像对比度,适用于需要特定灰度分布的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直方图均衡化的优点是能自动增强整个图像的对比度,但它的具体增强效果不易控制,处理的结果总是得到全局的均衡化的直方图.实际工作中,有时需要变换直方图使之成为某个特定的形状,从而有选择地增强某个灰度值范围内的对比度,这时可采用比较灵活的直方图规定化方法
 /*************************************************************************
 *
 * 函数名称:
 *   GrayStretch()
 *
 * 参数:
 *   LPSTR lpDIBBits    - 指向源DIB图像指针
 *   LONG  lWidth       - 源图像宽度(象素数)
 *   LONG  lHeight      - 源图像高度(象素数)
 *   BYTE bX1   - 灰度拉伸第一个点的X坐标
 *   BYTE bY1   - 灰度拉伸第一个点的Y坐标
 *   BYTE bX2   - 灰度拉伸第二个点的X坐标
 *   BYTE bY2   - 灰度拉伸第二个点的Y坐标
 *
 * 返回值:
 *   BOOL               - 成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数用来对图像进行直方图匹配。
 *
 ************************************************************************/
BOOL GrayStretch(LPBYTE lpDIBBits, LONG lWidth, LONG lHeight, BYTE bX1, BYTE bY1, BYTE bX2, BYTE bY2,BYTE bX3, BYTE bY3)
{
 
 // 指向源图像的指针
 unsigned char* lpSrc;
  
 // 规定直方图各灰度的分布概率
    float  fpP[256];
 
  // 临时变量
 LONG lTemp;
 int     A=0;
    LONG lTem=0;

    // 循环变量
 LONG i;
 LONG j;
 
 // 灰度映射表
 float bMap[256];
 
 // 各个灰度值的计数
 LONG m_lCount[256];
    BYTE    fpPu[256];

 
 // 图像每行的字节数
 LONG lLineBytes;
 
 // 计算图像每行的字节数
 //lLineBytes = WIDTHBYTES(lWidth * 8);
 lLineBytes=lWidth;
 // 计算灰度映射表
 for (i = 0; i <= bX1; i++)
 {
  // 判断bX1是否大于0(防止分母为0)
  if (bX1 > 0)
  {
   // 线性变换
   fpPu[i] = (BYTE) bY1 * i / bX1;
  }
  else
  {
   // 直接赋值为0
   fpPu[i] = 0;
  }
 }
 for (; i <= bX2; i++)
 {
  // 判断bX1是否等于bX2(防止分母为0)
  if (bX2 != bX1)
  {
   // 线性变换
     fpPu[i] = bY1 + (BYTE) ((bY2 - bY1) * (i - bX1) / (bX2 - bX1));
  }
  else
  {
   // 直接赋值为bY1
   fpPu[i] = bY1;
  }
 }
 for (; i < bX3; i++)
 {
  // 判断bX2是否等于255(防止分母为0)
  if (bX3 != bX2)
  {
   // 线性变换
   fpPu[i] = bY2 + (BYTE) ((bY3 - bY2) * (i - bX2) / (bX3 - bX2));
  }
  else
  {
   // 直接赋值为255
   fpPu[i] = 255;
  }
 }
  
 for (; i < 256; i++)
 {
  // 判断bX2是否等于255(防止分母为0)
  if (bX3 != 255)
  {
   // 线性变换
   fpPu[i]=bY3+(BYTE)((-bY3) * (i-bX3) / (255-bX3));
  }
  else
  {
   // 直接赋值为255
   fpPu[i] = 255;
  }
 }
 
// 积分计算
    for (i = 0; i < 256; i++)
 {
  // 初始为0 
  lTem += fpPu[i];
 }   
 // 每行
//**************************** 
 // 计算规定累计直方图
 for (i = 0; i < 256; i++)
 {
  // 初始为0
  lTemp = 0;
  
  for (j = 0; j <= i ; j++)
  {
   lTemp += fpPu[j];
  }
  
  // 计算对应的新灰度值
  fpP[i] = (BYTE) (lTemp * 255*1.0 /lTem);
 }

//****************************
// 计算原始累计直方图

 for (i = 0; i < 256; i ++)
 {
  // 清零
  m_lCount[i] = 0;
 }
  
 // 计算图像每行的字节数
 //lLineBytes = WIDTHBYTES(lWidth * 8);
 lLineBytes=lWidth;
 // 计算各个灰度值的计数
 for (i = 0; i < lHeight; i ++)
 {
  for (j = 0; j < lWidth; j ++)
  {
   lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
   
   // 计数加1
   m_lCount[*(lpSrc)]++;
  }
 }
// 计算灰度映射表
 for (i = 0; i < 256; i++)
 {
  // 初始为0
  lTemp = 0;
  
  for (j = 0; j <= i ; j++)
  {
   lTemp += m_lCount[j];
  }
  
  // 计算对应的新灰度值
  bMap[i] = (float) (lTemp * 255*1.0 / lHeight / lWidth);
 }

//****************************
 // 确定映射对应关系
 for (i = 0; i < 256; i++)
 {
  // 最小差值
  float min_value = 1.0f;


  // 对原始直方图分布进行枚举检索
  for (j = 0; j < 256; j++)
  {
   // 当前差值
   float now_value = 0.0f;
   
   // 计算差值
   if (bMap[i] - fpP[j] >= 0.0f)
    now_value = bMap[i] - fpP[j];
   else
    now_value = fpP[j] - bMap[i];
   
   // 寻找最接近的规定直方图灰度级
   if (now_value < min_value)
   {
    // 最接近的灰度级
    A=j;
    // 暂存最小差值
    min_value= now_value;
   }

  // 将[A1_r,A2_r]区间的原始灰度k通过建立映射表ns_r[]映射到灰度nu[i]
 
  }
  bMap[i]  = A;
 }

  
   // 每行
 for(i = 0; i < lHeight; i++)
 {
  // 每列
  for(j = 0; j < lWidth; j++)
  {
   // 指向DIB第i行,第j个象素的指针
   lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
   
   // 计算新的灰度值
   *lpSrc = bMap[*lpSrc];
  }
 }// 返回
 return TRUE;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值