原网址:http://blog.csdn.net/maozefa/article/details/43971063

阅读提示

    《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。

    《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。

    尽可能保持二者内容一致,可相互对照。

本文代码必须包括《C++图像处理 -- 数据类型及公用函数》文章中的BmpData.h头文件。


在Photoshop中,图像色阶调整应用很广泛,本文介绍的图像色阶调整过程与Photoshop处理效果基本一致。

Photoshop的色阶调整分输入色阶调整和输出色阶调整,其中输入色阶调整有3个调整点,即通常所说的黑场、白场及灰场调整。

输入色阶调整的基本算法并不复杂,首先计算出白场与黑场的离差Diff,然后计算出像素各份量值与黑场的离差rgbDiff,如果rgbDiff<=0,像素各份量值等于0,否则,计算以rgbDiff与Diff的比值为底的灰场倒数的幂。用公式表示:

Diff = Highlight -Shadow

rgbDiff = RGB - Shadow

clRGB = Power(rgbDiff / Diff,  1 / Midtones)

其中Shadow为输入色阶低端数据(黑场),Highlight为输入色阶高端数据(白场), Midtones为输入色阶中间数据(灰场),Diff为二者的离差(必须大于1),RGB为调整前的像素分量值,clRGB为调整输入色阶后的像素分量值。

输出色阶调整更简单,首先计算输出色阶白场与黑场的离差与255的比值系数,然后用输入色阶调整后的像素分量值乘上这个系数,再加上输出黑场值即可。用公式表示:

outClRGB = clRGB * (outHighlight - outShadow) / 255 + outShadow

其中,outShadow为输出黑场,outHighlight为输出白场,outClRGB为全部色阶调整后的像素分量值。

前面已经提到输入色阶黑白场的离差必须大于1,而输入色阶并没有这个限制,输出黑白场的离差可以为负数,当输出黑场与白场完全颠倒时,输出色阶调整后的图片为原图片的负片。

色阶调整涉及四个通道,即R、G、B各分量通道及整体颜色通道,如果每个通道单独调整,将是比较麻烦和耗时的,本文采用色阶表替换法,可一次性完成所有四个通道的色阶调整。

下面是图像色阶调整的代码:

[cpp] view plain copy
  1. // 色阶项结构
  2. typedef struct
  3. {
  4. UINT Shadow;
  5. FLOAT Midtones;
  6. UINT Highlight;
  7. UINT OutShadow;
  8. UINT OutHighlight;
  9. }ColorLevelItem, *PColorLevelItem;
  10. typedef struct
  11. {
  12. ColorLevelItem Blue;
  13. ColorLevelItem Green;
  14. ColorLevelItem Red;
  15. ColorLevelItem RGB;
  16. }ColorLevelData, *PColorLevelData;
  17. VOID InitColorLevelData(PColorLevelData clData)
  18. {
  19. PColorLevelItem item = &clData->Blue;
  20. for (INT i = 0; i < 4; i ++, item ++)
  21. {
  22. item->Shadow = item->OutShadow = 0;
  23. item->Highlight = item->OutHighlight = 255;
  24. item->Midtones = 1.0;
  25. }
  26. }
  27. BOOL GetColorLevelTable(PColorLevelItem item, LPBYTE clTable)
  28. {
  29. INT diff = (INT)(item->Highlight - item->Shadow);
  30. INT outDiff = (INT)(item->OutHighlight - item->OutShadow);
  31. if (!((item->Highlight <= 255 && diff < 255 && diff >= 2) ||
  32. (item->OutShadow <= 255 && item->OutHighlight <= 255 && outDiff < 255) ||
  33. (!(item->Midtones > 9.99 && item->Midtones > 0.1) && item->Midtones != 1.0)))
  34. return FALSE;
  35. DOUBLE coef = 255.0 / diff;
  36. DOUBLE outCoef = outDiff / 255.0;
  37. DOUBLE exponent = 1.0 / item->Midtones;
  38. for (INT i = 0; i < 256; i ++)
  39. {
  40. INT v;
  41. // 计算输入色阶黑白场
  42. if (clTable[i] <= (BYTE)item->Shadow)
  43. v = 0;
  44. else
  45. {
  46. v = (INT)((clTable[i] - item->Shadow) * coef + 0.5);
  47. if (v > 255)
  48. v = 255;
  49. }
  50. // 计算输入色阶灰场
  51. v = (INT)(pow(v / 255.0, exponent) * 255.0 + 0.5);
  52. // 计算输出色阶
  53. clTable[i] = (BYTE)(v * outCoef + item->OutShadow + 0.5);
  54. }
  55. return TRUE;
  56. }
  57. BOOL CheckColorLevelData(PColorLevelData clData, BYTE clTables[][256])
  58. {
  59. BOOL result = FALSE;
  60. INT i, j;
  61. for (i = 0; i < 3; i ++)
  62. {
  63. for (j = 0; j < 256; j ++)
  64. clTables[i][j] = (BYTE)j;
  65. }
  66. PColorLevelItem item = &clData->Blue;
  67. for (i = 0; i < 3; i ++, item ++)
  68. {
  69. if (GetColorLevelTable(item, clTables[i]))
  70. result = TRUE;
  71. }
  72. for (i = 0; i < 3; i ++)
  73. {
  74. if (!GetColorLevelTable(item, clTables[i]))
  75. break;
  76. result = TRUE;
  77. }
  78. return result;
  79. }
  80. // 图像数据色阶调整
  81. VOID ImageColorLevel(BitmapData *dest, BitmapData *source, PColorLevelData clData)
  82. {
  83. PARGBQuad pd, ps;
  84. UINT width, height;
  85. INT dstOffset, srcOffset;
  86. GetDataCopyParams(dest, source, width, height, pd, ps, dstOffset, srcOffset);
  87. BYTE clTables[3][256];
  88. if (CheckColorLevelData(clData, clTables))
  89. {
  90. for (UINT y = 0; y < height; y ++, ps += srcOffset, pd += dstOffset)
  91. {
  92. for (UINT x = 0; x < width; x ++, ps ++, pd ++)
  93. {
  94. pd->Blue = clTables[0][ps->Blue];
  95. pd->Green = clTables[1][ps->Green];
  96. pd->Red = clTables[2][ps->Red];
  97. pd->Alpha = ps->Alpha;
  98. }
  99. }
  100. }
  101. else if (dest != source)
  102. {
  103. for (UINT y = 0; y < height; y ++, ps += srcOffset, pd += dstOffset)
  104. {
  105. for (UINT x = 0; x < width; x ++, ps ++, pd ++)
  106. {
  107. pd->Color = ps->Color;
  108. }
  109. }
  110. }
  111. }

下面给一个简单的图像色阶调整函数调用例子:

[cpp] view plain copy
  1. void __fastcall TForm1::Button1Click(TObject *Sender)
  2. {
  3. BitmapData dest, source;
  4. Bitmap *sBmp = new Bitmap(L"..\\..\\media\\source1.jpg");
  5. LockBitmap(sBmp, &source);
  6. Bitmap *dBmp = new Bitmap(source.Width, source.Height, PixelFormat32bppARGB);
  7. LockBitmap(dBmp, &dest);
  8. ColorLevelData clData;
  9. InitColorLevelData(&clData);
  10. clData.RGB.Shadow = 10;
  11. clData.RGB.Midtones = 1.2;
  12. clData.RGB.Highlight = 240;
  13. clData.RGB.OutShadow = 50;
  14. clData.RGB.OutHighlight = 200;
  15. /*
  16. clData.RGB.OutShadow = 255;
  17. clData.RGB.OutHighlight = 0;
  18. */
  19. ImageColorLevel(&dest, &source, &clData);
  20. UnlockBitmap(dBmp, &dest);
  21. UnlockBitmap(sBmp, &source);
  22. Gdiplus::Graphics g(Canvas->Handle);
  23. g.DrawImage(sBmp, 0, 0);
  24. g.DrawImage(dBmp, source.Width, 0);
  25. delete dBmp;
  26. delete sBmp;
  27. }

下面是文章Delphi图像处理 -- 图像色阶调整例子运行界面效果图,第一张效果图绿色通道色阶调整,第二张效果图是RGB输出色阶调整到完全颠倒时的负片图,详细的图像色阶调整界面例子请参考Delphi图像处理 -- 图像色阶调整》。

本文代码系用BCB XE7编辑和编译。

    因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:maozefa@hotmail.com

这里可访问《C++图像处理 -- 文章索引》。

C++图像处理 -- 图像色阶调整相关推荐

  1. Photoshop图像处理算法—色阶调整

    前言:之前在公司做项目的用到photoshop颜色空间的一些相关方法,在此总结一下.下面原理部分是从我的总结文档里截取来的.需要复制的童鞋自己手写一下~ 2.程序部分 1)Matlab实验程序. cl ...

  2. OpenCV—python 色阶调整(直方图均衡化 图像去雾)

    文章目录 一.色阶调整( Levels Adjustment )原理 二.自动色阶图像处理算法 一.色阶调整( Levels Adjustment )原理 色阶:就是用直方图描述出的整张图片的明暗信息 ...

  3. Python+Opencv图像处理新手入门教程(二):颜色空间转换,图像大小调整,灰度直方图

    一步一步来吧 上一节:Python+Opencv图像处理新手入门教程(一):介绍,安装与起步 1.什么是图像 对于计算机而言,图像的本质是一个由像素点构成的矩阵. 例如我们用肉眼很容易分辨一辆汽车的后 ...

  4. 计算机图像处理实验四:图像对比度调整(MATLAB)

    [实验名称] 图像对比度调整 [实验目的] 通过本次实验掌握图像对比度自动调整技术: .熟悉使用库函数imhist.histeq:  [实验内容] 利用库函数imhist计算并分别显示下图(图1)中图 ...

  5. 使用TensorFlow进行常用的图像处理-图像转为矩阵以及图像大小调整

    图像编码处理 将图像转为一个三维矩阵,并使用三维矩阵形成一个图像: import tensorflow as tf import matplotlib.pyplot as plt# 读取原始图像数据 ...

  6. 【OpenCV 例程300篇】206. Photoshop 色阶调整算法

    OpenCV 例程200篇 总目录 201. 图像的颜色空间转换 202. 查表快速替换(cv.LUT) 203. 伪彩色图像处理 204. 图像的色彩风格滤镜 205. 调节色彩平衡/饱和度/明度 ...

  7. 使用Julia进行图像处理--图像表示与匹配算法

    使用Julia进行图像处理--图像表示与匹配算法 图像表示 特征和描述符 快速角点检测 使用imcorner函数进行角点检测 性能比较 BRIEF--有效检测重复图像的方法 识别图像重复项 使用多张图 ...

  8. python实现简单的ps色阶调整过程

    最近在做一个用unet神经网络识别种子出苗率的项目(种子贼小,分辨率还贼低),由于识别的效果不太好,只能对图像做预处理了...预处理选用的是ps中的色阶处理,可是cv2等图像库中没有现成的函数,只能自 ...

  9. C++图像处理 -- 图像颜色混合(下)

    阅读提示:     <C++图像处理>系列以代码清晰,可读性为主,全部使用C++代码.     <Delphi图像处理>系列以效率为侧重点,一般代码为PASCAL,核心代码采用 ...

最新文章

  1. comparator java_java:Comparator比较器
  2. OpenResty介绍
  3. CSS中盒模型的理解
  4. mysql 开发基础系列22 SQL Model(带迁移事项)
  5. linux mysql安装教程 方大帝_discuz论坛出现Can not connect to MySQL server错误的解决方法...
  6. .net宿舍管理系统 mysql_基于.NET CORE的精美后台管理系统-RuoYi C#版
  7. STM32工作笔记0030---编写跑马灯实验--使用库函数
  8. 分布式多副本一致性协议:paxos
  9. Atitit  代理与分销系统(1)  子代理 充值总额功能设计概览 sum() groubpy subagt
  10. 产业区块链一周动态丨数字货币发展写入十四五规划,湖南印发区块链发展规划...
  11. linux没有telnet命令
  12. Flutter跑马灯Marquee
  13. [黑马程序员C++笔记]P99-P104类和对象-封装
  14. idea的安装及基础设置
  15. python中的sort排序加换行_python中sort()排序的方法
  16. 海思NNIE开发(一):海思Hi3559AV100/Hi3519AV100 NNIE深度学习模块开发与调试记录
  17. java异常面试_java中异常的面试
  18. 下列实型常量不符合c语言,C语言程序设计考试题答案
  19. 第八次作业——Excel制作工资表
  20. python二进制方式读取文件,并将读取出的数据以txt的格式保存

热门文章

  1. mysql 存储过程 varchar 赋值,mysql 存储过程中变量的定义与赋值操作
  2. 【C语言】极坐标转换为直角坐标
  3. 第一章:Django入门篇
  4. J2EE struts2MVC应用在线书签1
  5. C++ 求长方体的体积
  6. 基于FPGA平台RISCV架构的SOC应用系统设计1
  7. Macbook环境配置之个人配置
  8. ring buffer 环形队列 C++实现
  9. 树冠点云投影面积计算(AlphaShape算法)
  10. n76e003引脚图_新唐推出N76E003高规格低管脚1T 8051单片机