本节为opencv数字图像处理(1):灰度变换与空间滤波的第一小节,灰度变换函数,主要包括:图像反转、对数变换、伽马变换、分段线性变换函数(包括对比度拉伸、灰度级分层和比特平面分层)及其C++代码实现。

1.1 图像反转

  sss和rrr分别表示处理前后的像素值,则应用反转变换可以得到灰度级范围为[0,L−1][0,L-1][0,L−1]的一幅图像的反转图像,由该式给出:s=L−1−rs=L-1-rs=L−1−r。
  这种反转图像灰度级的处理适用于增强嵌入在一幅图像的暗区域中的白色或灰色细节,特别是黑色面积在尺寸上占主导地位时。
  图像灰度级反转的C++代码如下:

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace std;
using namespace cv;
/*线性变化之灰度级反转*/
void grayInv()
{Mat srcImg = imread("test.PNG", 0);if (!srcImg.data) {cout << "fail to load image" << endl;return;}int k = -1, b = 255;int rowNum = srcImg.rows;int colNum = srcImg.cols;Mat dstImg(srcImg.size(), srcImg.type());for (int i = 0; i < rowNum; i++){uchar* srcData = srcImg.ptr<uchar>(i);for (int j = 0; j < colNum; j++) {dstImg.at<uchar>(i, j) = srcData[j] * k + b;}}imshow("original", srcImg);imshow("grayInv", dstImg);waitKey(0);
}

opencv4.3.0+Visual Studio 2019环境配置
waitKey的作用

1.2 对数变换

  sss和rrr分别表示处理前后的像素值,对数变换的通用形式可以表达为s=clog(1+r)s=clog(1+r)s=clog(1+r),ccc是一个常数。该变换的将输入中范围较窄的低灰度值映射为输出中较宽范围的灰度值,对高的输入灰度值也如此。从而实现扩展图像中暗像素的值同时压缩高灰度级的值的目的。一种简易的实现就是将上面给出的代码中像素操作替换为:

dstImg.at<uchar>(i, j)=log(double(1 + (double)srcImg.at<uchar>(i, j)));

  需要注意的是,之后我们需要进行灰度的归一化处理以使得灰度值分布在0-255之间,代码如下:

// 归一化处理cv::normalize(dstImg, dstImg,0, 255, cv::NORM_MINMAX);cv::convertScaleAbs(dstImg, dstImg);

1.3 幂律(伽马)变换

  sss和rrr分别表示处理前后的像素值,幂律变换的基本形式:s=crγs=cr^{\gamma}s=crγ。其中c和γ\gammaγ是正常数,有时考虑偏移量(输入为0)幂律变换也可以写为:s=c(r+ϵ)γs=c(r+\epsilon)^{\gamma}s=c(r+ϵ)γ。
  当γ<1\gamma<1γ<1时,与对数变换类似,幂律变换将较窄范围的暗色输入值映射为较宽范围的输出值,图像整体灰度值增大,用于提高图像暗区域中的对比度,而降低亮区域的对比度;当大于1时则相反,用于提高图像中亮区域的对比度,降低图像中按区域的对比度。
  C++代码如下:

void GammaCorr()
{Mat srcImg = imread("test.PNG");if (srcImg.empty()){cout << "fail to load" << endl;return;}float fGamma = 1 / 3.2;//建立待查表文件LUTunsigned char lut[256];for (int i = 0; i < 256; i++) {//防止彩色溢出,大于255的像素令其为255,小于0的像素令其为0lut[i] = saturate_cast<uchar>(pow((float)(i / 255.0), fGamma) * 255.0f);}Mat dstImg = srcImg.clone();const int channels = dstImg.channels();switch (channels){case 1://灰度图{MatIterator_<uchar> it, end;for (it = dstImg.begin<uchar>(), end = dstImg.end<uchar>(); it != end; it++)//*it = pow((float)(((*it)) / 255.0), fGamma) * 255.0;*it = lut[(*it)];break; }case 3://彩色图 {MatIterator_<Vec3b> it, end;for (it = dstImg.begin<Vec3b>(), end = dstImg.end<Vec3b>(); it != end; it++){//(*it)[0] = pow((float)(((*it)[0])/255.0), fGamma) * 255.0; //(*it)[1] = pow((float)(((*it)[1])/255.0), fGamma) * 255.0; //(*it)[2] = pow((float)(((*it)[2])/255.0), fGamma) * 255.0; (*it)[0] = lut[((*it)[0])];(*it)[1] = lut[((*it)[1])];(*it)[2] = lut[((*it)[2])];}break;}}imshow("ori", srcImg);imshow("res", dstImg);waitKey(0);
}
1.4 分段线性变换函数
  • 对比度拉伸

  低对比度图像的成因可能是照明不足、成像传感器动态范围太小或者图像获取过程中镜头光圈设置错误引起,对比度拉伸的作用是扩展图像灰度级动态范围。
  下图所示是一个典型的对比度拉伸变换的函数形状,不同的r1,r2,s1,s2r1,r2,s1,s2r1,r2,s1,s2取值也对应这不同的灰度级变换:当r1=s1r1=s1r1=s1且r2=s2r2=s2r2=s2,则是一个线性变换;当r1=r2,s1=0,s2=L−1r1=r2,s1=0,s2=L-1r1=r2,s1=0,s2=L−1(最大灰度级),则是一个阈值处理函数(产生一个二值图像)。
  针对灰度图像的对比度拉伸C++实现如下:

void contrastStretch()
{Mat srcOri = imread("test1.JPG");Mat srcImage;cvtColor(srcOri, srcImage, CV_RGB2GRAY);//"=";"clone()";"copyTo"三种拷贝方式,前者是浅拷贝,后两者是深拷贝。Mat resultImage = srcImage.clone();int nRows = resultImage.rows;int nCols = resultImage.cols;//判断图像存储的连续性,若连续可以得到像素个数if (resultImage.isContinuous()){nCols = nCols * nRows;nRows = 1;}//图像指针操作uchar* pDataMat;int pixMax = 0, pixMin = 255;//计算图像的最大最小值for (int j = 0; j < nRows; j++){//ptr<>()得到的是一行指针,智能指针+模板类pDataMat = resultImage.ptr<uchar>(j);for (int i = 0; i < nCols; i++){if (pDataMat[i] > pixMax)pixMax = pDataMat[i];if (pDataMat[i] < pixMin)pixMin = pDataMat[i];}}//对比度拉伸映射,从原始范围拉伸到num1~num2int num1 = 100, num2 = 200;for (int j = 0; j < nRows; j++){pDataMat = resultImage.ptr<uchar>(j);for (int i = 0; i < nCols; i++){pDataMat[i] = (pDataMat[i] - pixMin) * (num2 - num1) / (pixMax - pixMin) + num1;}}imshow("ori", srcImage);imshow("dst", resultImage);waitKey(0);
}
  • 灰度级分层

  灰度级分层可以突出图像中特定灰度范围的亮度,一种方式即感兴趣范围设为一个值,不感兴趣设置为另一个值;另一种方式是使感兴趣区域变亮或变暗,保持图像中其他的灰度级不变。两种方式的变换函数的形状如下图:

  具体实现的话可以对上述对比度拉伸的代码进行简单调整即可。

  • 比特平面分层
      下图显示了一个8比特灰度图像(第一幅)以及1~8比特的比特平面(后八幅)。可以直观看出,低阶比特平面在图像中贡献了更精细的灰度细节,高阶比特平面包含了视觉上很重要的大多数数据,

      显示一幅8比特图像的第8个比特平面可用阈值灰度变换函数处理输入图像得到二值图像,将0~127之间的灰度映射为0,其他的映射为1。比特平面分层以及使用几个高阶比特平面重构图像的作用在于图像压缩和突出部分比特特征。C++代码如下:
void bitLevel()
{Mat srcImage = imread("test2.JPG", 0);Mat d[8];int b[8];for (int k = 0; k < 8; k++)//CV_8UC1:其中8代表比特数,0~255;U代表无符号整型,F代表单精度浮点型;//C代表通道数;1代表灰度图像即单通道,2代表RGB彩色图像即三通道,3代表//带Alpha通道(透明度)的RGB图像,即四通道d[k].create(srcImage.size(), CV_8UC1);int rowNum = srcImage.rows, colNum = srcImage.cols;for (int i = 0; i < rowNum; i++)for (int j = 0; j < colNum; j++) {int num = srcImage.at<uchar>(i, j);//for (int p = 0; p < 8; p++)b[p] = 0;int q = 0;while (num != 0){b[q] = num % 2;num = num / 2;q++;}//for (int k = 0; k < 8; k++)d[k].at<uchar>(i, j) = b[k] * 255;}imshow("ori", srcImage);for (int k = 0; k < 8; k++)imshow("bit" + to_string(1 + k), d[k]);waitKey(0);
}

欢迎扫描二维码关注微信公众号 深度学习与数学   [每天获取免费的大数据、AI等相关的学习资源、经典和最新的深度学习相关的论文研读,算法和其他互联网技能的学习,概率论、线性代数等高等数学知识的回顾]

opencv数字图像处理(1) - 灰度变换函数相关推荐

  1. 【数字图像处理】灰度变换函数(对数变换、反对数变换、幂次变换)

    // 对比度增强.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h" #include <opencv2/opencv.hpp> #i ...

  2. OpenCV数字图像处理基于C++:灰度变换

    OpenCV数字图像处理基于C++:灰度变换 1.1 灰度变换概念 在图像预处理中,图像的灰度变换是图像增强的重要手段,灰度变换可以使图像对比度扩展,图像清晰,特征明显,灰度变换主要利用点运算来修正像 ...

  3. 《opencv 数字图像处理 图像基础》

    <opencv 数字图像处理 图像基础> 矩阵 通道分离和合并 彩色图像转灰度图像 灰度图转二值化图像 图像运算 矩阵 定义一个显示图像的函数,对于灰度图,里面添加了vmin=0,vmax ...

  4. OpenCV数字图像处理学习平台

    原始图像1-1 处理中的图像1-2 处理结果1-3(检测到所有圆) OpenCV数字图像处理学习平台,是一款可视化.交互式方式学习OpenCV的工具软件,由资深计算机视觉专家精心打造,花费近两年整理成 ...

  5. c++ opencv数字图像处理:频率域滤波--高通滤波--高斯高通滤波

    文章目录 前言 一.高斯高通滤波器(GHPF) 二.代码 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.高斯高通滤波器(GHPF) D 2 ( u , v ...

  6. c++ opencv数字图像处理:频率域滤波--低通滤波--理想低通滤波

    文章目录 前言 一.理想低通滤波器(ILPF) 二.代码 三.说明 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.理想低通滤波器(ILPF) 通过设置频率半 ...

  7. c++ opencv数字图像处理:频率域滤波--低通滤波--巴特沃斯低通滤波

    文章目录 前言 一.巴特沃斯低通滤波器(BLPF) 二.代码 三.说明 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.巴特沃斯低通滤波器(BLPF) D2( ...

  8. c++ opencv数字图像处理:频率域滤波--高通滤波--巴特沃斯高通滤波

    文章目录 前言 一.巴特沃斯高通滤波器(BHPF) 二.代码 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.巴特沃斯高通滤波器(BHPF) D2(u,v)为 ...

  9. c++ opencv数字图像处理:频率域滤波--高通滤波--理想高通滤波

    文章目录 前言 一.理想高通滤波器(IHPF) 二.代码 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.理想高通滤波器(IHPF) 二.代码 主代码: #i ...

  10. c++ opencv数字图像处理:访问图像像素,遍历图像像素

    文章目录 前言 一.访问图像像素 1.访问(j,i)处像素 2.例子:在图像中加入白色椒盐噪声 二.遍历图像像素 1.指针扫描 2.opencv自带的卷积运算:filter2D 前言 数字图像处理c+ ...

最新文章

  1. spark 算子例子_10年大数据架构师,用一文带你玩转Spark计算框架,你能读懂吗?...
  2. org.apache.log4j.Logger详解
  3. 将选定的文本对象左对齐、右对齐或对中
  4. 集群调度框架的架构演进之路
  5. java8 LocalDate 日期比较大小
  6. Stack Overflow上最热门问题是什么?
  7. xxl-job使用实例
  8. 永劫无间大神玩家ZX迷恋上单人三排,单局28杀,过程太过瘾了
  9. Windows Server 2012 R2 里面如何安装Net Framework 3.5
  10. linux云服务器上安装JDK
  11. Internet Download Manager(IDM下载器)
  12. NOI题库练习1.5(07)
  13. 计算机航嘉快捷启动键,win7 u盘启动快捷键是什么|win7 u盘启动按哪个键
  14. 如何远程操作另一台电脑,看这里就够了,远程控制另一台电脑的操作
  15. 四、快速搭建一套现代化的个人独立博客系统,给爱写博客的你(part2 正文)
  16. 想知道录屏软件免费版有哪些?这4个工具能够做到,建议收藏备用
  17. 持NPDP证书在深圳可享受子女入学、医疗保健、安居保障等福利
  18. 佳能canon e510打印机驱动 1.0 官E510 series XPS 打印机驱动程序 v. 5.62 (Windows)
  19. ML-czy的小组任务4
  20. Adobe AE CC切换语言 中英文切换

热门文章

  1. BFC --- Block Formatting Context --- 块级格式化上下文
  2. 对比iOS网络组件:AFNetworking VS ASIHTTPRequest
  3. mybatis实战教程(mybatis in action)之四:实现关联数据的查询(转)
  4. POJ1546(进制转换)
  5. 2011-9-11 凌晨00:46
  6. 设备和驱动器中删除空白图标
  7. ZeroClipboard—ZeroClipboard的使用
  8. SpringBoot常用注解之@Retryable
  9. 22. 栈的压入、弹出队列(C++版本)
  10. 为什么使用close()关闭所打开文件