当前位置:   article > 正文

C++数字图像处理(2)—分段线性拉伸_c++图片拉伸

c++图片拉伸

1、算法原理

    分段线性拉伸算法是图像灰度变换中常用的算法,在商业图像编辑软件Photoshop中也有相应的功能。分段线性拉伸主要是用于提高图像对比度,突显图像细节。设输入图像为f(x),输出图像为f'(x),分段区间为[start end]映射区间为[sout eout]。分段线性拉伸示意图如下:

图(1)分段线性拉伸示意图

    从图(1)可以明显得到,分段线性拉伸算法需要明确4个参数start、end、sout以及eout。当这个四个参数均已知时,根据两点确定直线法,计算出直线L1、L2和L3的参数,分别为(K1、C1=0)、(K2、C2)和(K2、C2)。那么分段线性拉伸算法的公式如下:

    对于参数分段区间[start end]以及映射区间[sout eout],有人工设定、基于直方图设定等办法。下面我们先实现核心算法功能,再实现参数半自动选取功能(基于直方图的分段线性拉伸)。

2、算法实现

    由于分段线性拉伸也是图像灰度变换的一种,所以,在这篇文章中同样使用查表的方式进行算法实现。灰度变换查表法实现

  1. //函数名:dividedLinearStrength
  2. //作用:实现分段线性拉伸
  3. //参数:
  4. //matInput:输入图像
  5. //matOutput : 输出图像
  6. //fStart : 分段区间起点
  7. //fEnd : 分段区间终点
  8. //fSout:映射区间起点
  9. //fEout:映射区间终点
  10. //返回值:无
  11. //注:支持单通道8位灰度图像
  12. void dividedLinearStrength(cv::Mat& matInput, cv::Mat& matOutput, float fStart, float fEnd,
  13. float fSout, float fEout)
  14. {
  15. //计算直线参数
  16. //L1
  17. float fK1 = fSout / fStart;
  18. //L2
  19. float fK2 = (fEout - fSout) / (fEnd - fStart);
  20. float fC2 = fSout - fK2 * fStart;
  21. //L3
  22. float fK3 = (255.0f - fEout) / (255.0f - fEnd);
  23. float fC3 = 255.0f - fK3 * 255.0f;
  24. //建立查询表
  25. std::vector<unsigned char> loolUpTable(256);
  26. for (size_t m = 0; m < 256; m++)
  27. {
  28. if (m < fStart)
  29. {
  30. loolUpTable[m] = static_cast<unsigned char>(m * fK1);
  31. }
  32. else if (m > fEnd)
  33. {
  34. loolUpTable[m] = static_cast<unsigned char>(m * fK3 + fC3);
  35. }
  36. else
  37. {
  38. loolUpTable[m] = static_cast<unsigned char>(m * fK2 + fC2);
  39. }
  40. }
  41. //构造输出图像
  42. matOutput = cv::Mat::zeros(matInput.rows, matInput.cols, matInput.type());
  43. //灰度映射
  44. for (size_t r = 0; r < matInput.rows; r++)
  45. {
  46. unsigned char* pInput = matInput.data + r * matInput.step[0];
  47. unsigned char* pOutput = matOutput.data + r * matOutput.step[0];
  48. for (size_t c = 0; c < matInput.cols; c++)
  49. {
  50. //查表gamma变换
  51. pOutput[c] = loolUpTable[pInput[c]];
  52. }
  53. }
  54. }

参数设置fstart = 72、fEnd = 200、fSout=5、fEout=240,调用函数如下:

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. cv::Mat matSrc = cv::imread("../分段线性拉伸.jpg", cv::IMREAD_GRAYSCALE);
  4. cv::imshow("原始图", matSrc);
  5. cv::Mat matDLS;
  6. dividedLinearStrength(matSrc, matDLS, 72, 200, 5, 240);
  7. cv::imshow("分段线性拉伸", matDLS);
  8. cv::waitKey(0);
  9. return 0;
  10. }

运行效果如下:

图(2)分段线性拉伸

3、基于直方图的分段线性拉伸

    基于直方图的分段线性拉伸算法主要改进在于,通过从直方图自动地计算出分段区间和映射区间四个参数。本质上,直方图是对图像像素进行排序的一个过程。根据分段线性拉伸的原理,对图像像素进行升序排序后,取高灰度等级NH个点对应的最小灰度作为fEnd,取低灰度等级NL个点对应的最大灰度等级作为fStart,fSout = fStart * Sigma, fEout = fEnd * (1+sigma),sigma < 1。具体代码实现步骤为:

(1)、统计直方图。

(2)、计算分段区间和映射区间。为使参数与图像尺寸无关,使用比例的方法限定NH和NL。设图像尺寸为MXN,高灰度等级个数比例为fH、低灰度等级个数比例为fL。

(3)、分段线性拉伸。

具体代码实现如下:

  1. //函数名:dlsBaseHistogram
  2. //作用:基于直方图的分段线性拉伸
  3. //参数:
  4. //matInput:输入图像
  5. //matOutput : 输出图像
  6. //fH : 高灰度等级比例
  7. //fL : 低灰度等级比例
  8. //fSigma:拉伸系数
  9. //返回值:无
  10. //注:支持单通道8位灰度图像
  11. void dlsBaseHistogram(cv::Mat& matInput, cv::Mat& matOutput, float fH, float fL, float fSigma)
  12. {
  13. //统计直方图
  14. std::vector<int> histogram(256);
  15. for (size_t r = 0; r < matInput.rows; r++)
  16. for (size_t c = 0; c < matInput.cols; c++)
  17. {
  18. histogram[matInput.at<unsigned char>(r, c)]++;
  19. }
  20. //计算分段区间
  21. int nNH = matInput.rows * matInput.cols * fH;
  22. int nNL = matInput.rows * matInput.cols * fL;
  23. int nACC = 0;
  24. float fStart = 0, fEnd = 0;
  25. for (size_t m = 255; m >= 0; m --)
  26. {
  27. nACC += histogram[m];
  28. if (nACC > nNH)
  29. {
  30. fEnd = m;
  31. break;
  32. }
  33. }
  34. nACC = 0;
  35. for (size_t m = 0; m < histogram.size(); m++)
  36. {
  37. nACC += histogram[m];
  38. if (nACC > nNL)
  39. {
  40. fStart = m;
  41. break;
  42. }
  43. }
  44. //计算映射区间
  45. float fSout = fStart * fSigma;
  46. float fEout = fEnd * (fSigma + 1.0f);
  47. fEout = fEout > 255.0f ? 254 : fEout;
  48. //分段线性拉伸
  49. dividedLinearStrength(matInput, matOutput, fStart, fEnd, fSout, fEout);
  50. }
图(3)fH = 0.2 fL = 0.5 fSigma = 0.5 拉伸结果
 
技术交流合作QQ:3355138068
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/78934
推荐阅读
相关标签
  

闽ICP备14008679号