• 数字图像处理(MATLAB版)学习笔记(2)——第2章 灰度变换与空间滤波


    0、小叙闲言

    续第一章之后,对数字图像和图像处理略有了解。第二章内容有不少,书中编写了很多的函数,还是一样,只要沉下心看看,理清楚结构,看明白功能,个人觉得很容易看明白。同时书中的代码都有很多的注释,更加减少我们看代码的难度。耐心,静心,定会有所收获。

    1、本章整体结构

    本章内容很多,也有很多的数学知识,个人在学习的时候,碰到了好多困难,毕竟不是科班出生,而且也没有学习过数字信号处理,还好,线性代数和概率论学得还可以,但依旧有不少不理解的地方。下面也只能整理一下书中的知识要点,以后有新的领悟再来更新,看下面一章,关于离散傅里叶变换,好像更难。

    2、书中例子

    例2.1 主要是使用函数imadjust,来熟悉一下灰度处理,体验一把

    >> imread('myimage.jpg');
    >> f=imread('myimage.jpg');
    >> g1 = imadjust(f, [0 1], [1 0]);
    >> imshow(g1);
    >> imshow(f);
    >> g2 = imadjust(f, [0.5 0.75], [0 1]);
    >> figure;imshow(g2);
    >> g3 = imadjust(f, [], [],2);
    >> figure;imshow(g3);

    处理前后效果,还可以,f到g1的变换,就是对像素值进行了反转,也就是书中所讲的负片效果,对医学很有用。

    g2图是将[0.5 0.75]间的像素线性变换到[0 1]之间,也就是进行了放大。那么这里有点疑问,我们的图像像素幅值区间不可能只是有[0.5 0.75],这个参数的意义到底是什么呢?我对书中的理解如下,上面图中所用到的是uint8类型图像,因此图像幅值区间是[0 255],有一点编程基础的都应该清楚。所以对应uint8类型,它的实际区间为[0.5 0.75]*255=[127.5  191.25]。如果是对应是uint16类型,那么他的实际区间为[0.5 0.75]*(2^16-1)=[32767 49151],也就是只取区间[32767 49151]像素幅值。再回到imadjust(f, [0.5 0.75], [0 1]),也就是将区间[127.5  191.25]映射到[0 255],怎么一个映射法呢?默认的就是线性对应,由两点(两个区间形成两点)确定一条直线。如下图所示:

    那么问题又来了,如果是区间[0.5 0.75]映射到[1 0]又是如何理解的呢,其实是一样的道理,做好点对点的对应关系,求出线性函数即可。如下图所示的对应关系,这也就解释了g1图效果的原因,从[0 1]映射到[1 0],就是斜率为-1,x取值范围为[0 255],完全就是一个线性明暗反转操作。

    Low_High=strechlim(f),就是帮我们找到图像f中的像素幅值的最大值和最小值,如果f是一个单值图像,那么Low_High就是一个行向量(1*2的矩阵),如果f是一个彩色图像,那么Low_High就是一个3*2的矩阵。当我们找到f图像的最小,最大像素幅值后,再将其映射到整个像素区间[0 1],也就是书中所讲,实现对比度拉伸,可以得到不错的效果。如下图,从A图到D图,D图就是使用了strechlim(f),然后使用D=imadjust(f,Low_High,[0 1]);得到的图像,很是清晰。

    书中的一个tofloat函数,很短,但写得很棒,我读了一下,并添加了一些自己的注释,代码如下。

     1 function [out, revertclass] = tofloat(in)
     2 %out=输入的图像参数(in)转化为float型数据点
     3 %revertclass=一个函数句柄可以将类型转回去
     4 
     5 identity = @(x) x;        %一个匿名函数的句柄,表示自身
     6 tosingle = @im2single;    %普通函数句柄 理解为函数指针也行
     7 tabel = {
     8         'uint8',     tosingle,   @im2uint8
     9         'uint16',    tosingle,   @im2uint16
    10         'int16',     tosingle,   @im2uint16
    11         'int16',     tosingle,   @logical
    12         'double',    identity,   identity
    13         'single',    identity,   identity
    14 };
    15 %在单元矩阵的第1列中找到输入参数类型的名字
    16 classIndex = find(strcmp(class(in), tabel(:, 1)));
    17 
    18 if isempty(classIndex)
    19     error('Unspported input image class.');
    20 end
    21 %在单元矩阵的第2列中找到索引处转为flaot型的函数句柄,进行转换
    22 out = tabel{classIndex, 2}(in);
    23 %在单元矩阵的第3列中找到索引处反转为原来类型函数句柄,进行转换
    24 revertclass = tabel{classIndex, 3};

     运用例中的代码做两个图看看,练练手,效果如下:

    h=imhist(f,25);
    horz = linspace(0,255,25);
    subplot(1,2,1);bar(horz,h);
    subplot(1,2,2);stem(horz, h, 'fill');

    3、个人对书中一些知识的理解

    书中intrans函数的的结构如下,书中写了比较长的代码,但并不复杂。只是在下面结构基础上添加了一些逻辑判断,增加了代码的长度,算法不复杂。

    本质就是对前面灰度变换方法的一个综合,书中函数代码写了很长,其实都很容易,大部分代码都是在做一个判断,减少函数的bug。

    书中重新编写的g = gscale(f, method, low, high)函数,也就是实现前文所讲的,灰度全尺度拉伸变换,个人觉得其实配合,stretchlim函数和imadjust可以轻松完成此功能。

    心得总结

    学习本章,深深感受好数学功底太重要了,很多理论如果对数学没有一定的了解,很难理解原理。只能掌握一些关于图像处理的方法。这跟当年学习单片机是一样的,很多的电路原理都不太清楚,但是照着别人的方法和步骤来编程,一样可以取得想要的效果。当使用单片机多了,接触得更多了,慢慢以也就理解了。目前学习数字图像处理的我,正像是当年第一次接触单片机一样。很多图像处理的算法,虽然书上说了,但我还是不理解,只能照着书上的来,然后也得到了书上的效果。

    在知乎上搜索如何学习数字图像处理这一话题时,有很多人跟我一样,也是不能理解其中的算法原理,有一些知乎的大神也给出了建议,第一次学习,书中诸多难以理解的算法,暂且可不用刨根问底。先掌握数字图像处理这一技能,而后理解数字图像处理这一心法,最后化为自己的内功。自身不是天才,无法一次就能掌握。

  • 相关阅读:
    “ResGen.exe”已退出,代码为2 问题处理
    在不同域中各个系统拥有自已独立的用户系统时的单点登录问题
    SQL SERVER 表分区
    用《捕鱼达人》去理解C#中的多线程
    浅谈ThreadPool 线程池(引用)
    解决chrome和firefox flash不透明的方法
    浅谈CSRF攻击方式(转)
    SQL语句创建相同结构的表
    如何识别伪静态网页
    在drop user之前,建议获取该用户的依赖情况
  • 原文地址:https://www.cnblogs.com/endlesscoding/p/6681142.html
Copyright © 2020-2023  润新知