【vc++精品源码栏目提醒】:网学会员为广大网友收集整理了,VC++数字图像处理源程序及详解之5(灰度拉伸) - 计算机教材,希望对大家有所帮助!
本节介绍灰度拉伸的相关知识, 它是改变图像对比度的常用方法。
由于环境光线或采集设备等原因,图像的灰度有时会集中于某一较小区间,如图像过亮或过暗等,这时就需要对图像 的灰度进行拉伸使之覆盖较大的取值区间,从而提高图像的对比度以便于观察。
这种处理就可以利用线性变换曲线建立灰度映射来完成。
灰度拉伸又叫做对比度拉伸,它与线性变换有些类 似,不同之处在于灰度拉伸使用的是分段线性变换,所以它最大的优势是变换函数可以由用户任意合成。
灰度拉伸的公式为: 其变换函数的图形如图9-27所示。
图9-27 灰度拉伸函数的图形 可见,灰度拉伸需要指定两个控制点,它们用于控制 灰度拉伸变换函数的图形。
一般情况下有x2≥x1 y2≥y1成 立。
正如其名,灰度拉伸常用于扩展指定灰度范围,以改善图像质量。
接下来通过讨论控制点来分析灰度拉伸的作用。
1) 即中间线段的斜率大于1,如果一幅图像对比度较 低,就可以利用这类控制点对图像进行对比度拉伸,如图9-28所示。
图9-28 利用灰度拉伸增加图像的对比度 从图9-28中可以明显发现原始图像的对比度较 低,其灰度分布主要集中在50~150的范围内。
经过(50 20)、(150 230)两个控制点的灰度拉伸变换后,灰度分布范围被拉伸了,达到了20~230,图像的对比度大大增加,整体显示效果得到加强。
2) 即中间线段的斜率小于1,作用与上一条刚好相反, 用于降低图像的对比度,如图9-29所示。
图9-29 利用灰度拉伸降低图像的对比度 9-29图中的原始图像对比度较高,但是经过控制 点为20 50、230 120的灰度拉伸后,图像的灰度分布基本被压缩在50~120之间。
变换后的图像对比度降低,整体画面偏灰色。
3) 此时变换 函数变化为一条线性函数,它将产生一个没有变化的图像。
4) 这也是一种特殊情况,此时变换函数变为阈值函数, 产生二值图像,效果见9.4节。
下面的函数实现了图像的灰度拉伸变换。
/ 作用: 灰度拉伸函数 参数: pixel: 原始像素数组 tempPixel: 保存变换后图像的像素数组 width: 原始图像宽度 X1Y1: 控制点1的坐标 X2Y2: 控制点2的坐标 / void GrayStretchBYTE pixel BYTE tempPixel UINT width UINT height float X1 float Y1 float X2 float Y2 // 映射表,用于256种灰度变换后的值 BYTE map256 // 保存运算后的临时值 double dTemp for int x 0 x 256 x // 如果在第一条直线上 if x X1 if fabsX1 - 0 0.0001 dTemp floatY1 / floatX1 x else dTemp 0 // 如果在第二条直线上 else if x 0.0001 dTemp floatY2 - Y1 / floatX2 - X1 x - X1 Y1 else dTemp x // 如果在第三条直线上 else if fabsY2 - 255 0.0001 dTemp float255 - Y2 / float255 - X2 x - X2 Y2 else dTemp 255 // 四舍五入 mapx intdTemp 0.5 // 变换后的值直接在映射表中查找 for UINT i 0 i width height i int x pixeli 4 tempPixeli4 tempPixeli41 tempPixeli42 mapx tempPixeli43 255 本节利用对话框实现灰度拉伸的功能,对话框效果如 图9-29所示。
用户可以在文本框中修改两个控制点的坐标,或者直接利用鼠标拖动预览框中的红点改变控制点。
下面完成该对话框的设计。
打开 MagicHouse项目,添加一个新的对话框资源,将其ID改名为IDD_STRETCH,然后创建对话框类CStretchDlg。
最后根据图 9-30和表9-5完善灰度拉伸对话框。
图9-30 灰度拉伸对话框的设计 表9-5 灰度拉伸对话框资源与变量的关系 1 图片控件 IDC_PREV CStatic m_stiPrev 2 文本框 IDC_POINTONE_X float m_dPsX1 3 文本框 IDC_POINTONE_Y float m_dPsY1 4 文本框 IDC_POINTTWO_X float m_dPsX2 5 文本框 IDC_POINTTWO_Y float m_dPsY2 灰度拉伸 对话框的实现难点是如何利用鼠标改变两个控制点。
为方便读者理解,这里使用流程图的方式解释,流程图如图9-31所示。
图9-31 拖动的响应流程图 由此可见,灰度拉伸对话框是依靠 m_bIsDraging与m_nPointType共同判断是否为拖动操作的。
如果满足条件,由OnMouseMove函数完成拖动操作的全部过程,最 后更新预览框。
下面给出StretchDlg.h的代码清单: pragma once include afxwin.h include PreviewDlg.h // CStretchDlg 对话框 class CStretchDlg : public CDialog // 当前操作控制点类型 enum PointType PT_NULL // 控制点1 PT_POINT_ONE // 控制点2 PT_POINT_TWO // 控制点3 DECLARE_MESSAGE_MAP DECLARE_DYNAMICCStretchDlg public: CStatic m_stiPrev // 图像预览框 float m_dPsX1 // 控制点1的x坐标 float m_dPsY1 // 控制点1的y坐标 float m_dPsX2 // 控制点2的x坐标 float m_dPsY2 // 控制点2的y坐标 // 标准构造析构函数 CStretchDlgCWnd pParent NULL virtual CStretchDlg void Refresh // 刷新预览框 virtual BOOL OnInitDialog // 对话框初始化 afx_msg void OnPaint // 重新绘制对话框 afx_msg void OnEnChangePointoneX // 改变控制点1的x坐标时的响应函数 afx_msg void OnEnChangePointoneY // 改变控制点1的y坐标时的响应函数 afx_msg void OnEnChangePointtwoX // 改变控制点2的x坐标时的响应函数 afx_msg void OnEnChangePointtwoY // 改变控制点2的y坐标时的响应函数 afx_msg void OnMouseMoveUINT nFlags CPoint point // 鼠标移动时响应拖动动作 afx_msg void OnLButtonDownUINT nFlags CPoint point // 按下鼠标左键的响应函数 afx_msg void OnLButtonUpUINT nFlags CPoint point // 释放鼠标左键的响应函数 afx_msg BOOL OnSetCursorCWnd pWnd UINT nHitTest UINT message // 设置鼠标光标 afx_msg void OnBnClickedSave // “保存”按钮响应函数 afx_msg void OnBnClickedOk // “确定”按钮响应函数 protected: virtual void DoDataExchangeCDataExchange pDX // DDX/DDV 支持 private: CPreviewDlg dlg // 预览对话框 bool m_bModify // 图像是否被修改 bool m_bIsDraging // 是否正在拖动控制点 int m_nPointType // 当前操作控制点类型 // 对话框数据 enum IDD IDD_STRETCH 由于篇幅有限,这里不再给出StretchDlg. cpp的实现代码,读者请到指定网站下载。
打开“菜单栏”资源,在“点运算”菜单下添加一个 新项“灰度拉伸”,其ID为ID_POINT_STRETCH,如图9-32所示。
图9-32 在菜单栏资源上添加新项 然后添加响应函数 OnPointStretch,其内容请读者参看源代码。
上一篇:
【精品文档】:编译程序后,连接的时候出现如下的错误,该怎么解决
下一篇:
青青子衿,悠悠我心