├── CH01_CH02 ├── chapter1_chapter2.md └── picture │ ├── data_form.PNG │ ├── imfinfo_form.PNG │ ├── judge_func1.PNG │ ├── judge_func2.PNG │ ├── logic_func.PNG │ ├── max.PNG │ ├── operator.PNG │ ├── rw_frame.PNG │ └── standard_ndrray.PNG ├── CH03 ├── chapter3.md ├── imadjust_test.py └── images │ ├── contrast.PNG │ ├── contrast_em.PNG │ ├── fspecial.PNG │ ├── gamma.PNG │ ├── imfilter.PNG │ ├── laplac.PNG │ ├── log_em.PNG │ └── plot.PNG ├── CH06 ├── chapter6.md └── images │ ├── G_x.PNG │ ├── colorgrad.PNG │ ├── colormap.PNG │ ├── colorseg1.PNG │ ├── colorseg2.PNG │ ├── ice.PNG │ ├── mahalabis.PNG │ ├── mahalobis │ ├── 1.PNG │ ├── 2.PNG │ └── 3.PNG │ └── rgb_ind_gray.PNG ├── CH09 ├── chapter9.md └── images │ ├── hat.PNG │ ├── imdilate.PNG │ ├── morph.PNG │ ├── open_close.PNG │ ├── seperate.PNG │ ├── set_operate.PNG │ ├── strel.PNG │ ├── struct_yuansu.PNG │ └── zhiwen.PNG ├── CH10 ├── chapter10.md └── images │ ├── HOUGH.PNG │ ├── edge.PNG │ ├── line.PNG │ └── suanzi.PNG ├── CH11 ├── chapter11.md └── images │ ├── bianjiepianduan.PNG │ ├── biaoji.PNG │ ├── diff.PNG │ └── lianma.PNG ├── README.md └── higher_order_algorithm ├── BoW.md ├── LBP.md ├── SIFT.md ├── affine_transformation.md ├── images ├── DOG.PNG ├── diff1.png ├── diff2.png ├── diff3.PNG ├── digram.PNG ├── dog_p.PNG ├── fangxiang.PNG ├── gauss.PNG ├── ni.PNG ├── pyramid.PNG ├── pyramid_table.PNG ├── pyramidf.PNG ├── sift_con.PNG └── updown.PNG └── similarity_transformation.md /CH01_CH02/chapter1_chapter2.md: -------------------------------------------------------------------------------- 1 | # 第一章 绪论 2 | 使用MATLAB图像处理工具箱IPT函数,并且本书开发了新函数,每个函数的源代码包含在各章节或附录C中 3 | # 第二章 基本原理 4 | ## Matlab支持图片格式 5 | ![logo](./picture/rw_frame.PNG) 6 | ## 图像操作 7 | 1.读取图像:`f=imread('xxxx.jpg')` 8 | 2.读取行列:`[m,n]=size(f)`, `whos f`显示数组附加信息。第一维表示垂直方向,`size(f,1)`表示行数 9 | 3.显示图像:`imshow(f,G)` 若将G省略,默认灰度级数为256;`G=[low high]`表示low以下为黑,high以上为白;`G=[ ]`表示low默认为f中最小值,high为最大值 10 | 4.函数pixval:交互显示单个像素亮度值;若按住鼠标左键不放,可用于测量距离 11 | 5.保存图像:`imwrite(f,'xxxx.jpg')` 12 | * JPEG压缩:`imwrite(f,'xxx.jpg','quality',q)` q为0-100的整数,q越小图像退化越严重 13 | * 可用imfinfo计算压缩率 14 | 15 | ``` 16 | K=imfinfo('test.jpg'); 17 | image_bytes = K.Width*K.Height*K.BitDepth/8; 18 | compressed_bytes = K.FileSize; 19 | compressed_ratio = image_bytes/compressed_bytes; 20 | ``` 21 | 22 | K结构体成员如下图 23 | ![logo](./picture/imfinfo_form.PNG) 24 | * tif同分辨率尺寸缩放 25 | 26 | ## 数据类 27 | ![logo](./picture/data_form.PNG) 28 | 29 | ## 图像类型 30 | * 亮度图像(Intensity images) 31 | * 二值图像(Binary images):数据类为logical。A为由0、1构成的数值数组,`B=logical(A)`,islogical判断 32 | * 索引图像(Indexed images) 33 | * RGB图像(RGB images) 34 | 35 | ## 数据类与图像数据类型间的转换 36 | * 数据类转换:B=logical(A)或uint8(A); double转uint8,会将[0 255]以外去掉,然后去掉小数点部分 37 | * 图像类型转换: 38 | - im2uint8:[0 1]范围内乘255,范围外置为0,1。 39 | - im2uint16:与int8类似,65535。 40 | - mat2gray:只能输入double,转换为[0 1]的double;mat2gray(A,[Amin,Amax])规定转换后的0,1。 41 | - im2double:若输入为uint8,每个值除以255;若为uint16,除以65535。 42 | - im2bw:`im2bw(f,T)`T的取值为[0 1];若输入uint8,会先每个值除以255;可以用关系运算'gb=f>2'替代。 43 | 44 | ## 数组索引 45 | * 向量索引:v([1 4 7]) 46 | * 矩阵索引: 47 | 1.A(D),D为逻辑数组,将所有为1的以列向量排列 48 | 2.一个:,将全部元素以逐列形式排成一个列向量,sum(A(:))等价于sum(sum(A)) 49 | ### 例2.5 50 | * 垂直翻转`fp=f(end:-1:1,:);` 51 | * 二次取样`fs=f(1:2:end,1:2:end);` 52 | 53 | ## 标准数组 54 | ![logo](./picture/standard_ndrray.PNG) 55 | ## 运算符 56 | 1.算数运算符 57 | ![logo](./picture/operator.PNG) 58 | * max&min 59 | ![logo](./picture/max.PNG) 60 | 2.关系运算符 ~= 61 | 3.逻辑运算符 & | ~ 62 | ![logo](./picture/logic_func.PNG) 63 | ![logo](./picture/judge_func1.PNG) 64 | ![logo](./picture/judge_func2.PNG) 65 | 66 | ## 代码优化 67 | * tic toc 计时;t1/(t2+eps) 68 | * 预分配数组 69 | 70 | ## 单元数组与结构体 71 | ``` 72 | //单位数组 73 | c={'guess',[1;2],3} 74 | c{1} 75 | ``` 76 | ``` 77 | //结构体 78 | field='first'; 79 | value=1; 80 | c=struct(field,value); 81 | ``` 82 | -------------------------------------------------------------------------------- /CH01_CH02/picture/data_form.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/data_form.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/imfinfo_form.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/imfinfo_form.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/judge_func1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/judge_func1.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/judge_func2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/judge_func2.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/logic_func.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/logic_func.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/max.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/max.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/operator.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/operator.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/rw_frame.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/rw_frame.PNG -------------------------------------------------------------------------------- /CH01_CH02/picture/standard_ndrray.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH01_CH02/picture/standard_ndrray.PNG -------------------------------------------------------------------------------- /CH03/chapter3.md: -------------------------------------------------------------------------------- 1 | # gamma变换 2 | * 数学原理 3 | 幂等变换:$I=cI^\gamma$ 4 | ![logo](./images/gamma.PNG) 5 | * MATLAB 6 | ``` 7 | g=imadjust(f,[low_in high_in],[low_out high_out],gamma) 8 | %[]默认[0 1];若low_out>high_out,亮度反转 9 | %gamma>1,曲线上弯,变亮,从而进行对比度增强;gamma<1,曲线下弯,变暗,从而进行灰度级压缩。 10 | ``` 11 | * python 12 | ```python 13 | #自己编的函数复现MATLAB的imadjust函数, 14 | # img_mono单通道图像,[low_in,high_in]到[0,1]映射,out_inverse=1时为到[1,0]的映射 15 | def imadjust(img_mono, gamma, low_in=0, high_in=255, out_inverse=0): 16 | # img_mono单通道图像,[low_in,high_in]到[0,1]映射,out_inverse=1时为到[1,0]的映射 17 | # 将[low_in,high_in]以外值减掉,向量化 18 | image_trunc = (img_mono > high_in) * high_in + (img_mono <= high_in) * img_mono 19 | image_trunc = (image_trunc < low_in) * low_in + (image_trunc >= low_in) * image_trunc 20 | # 归一化0-1 21 | img_adjust = (image_trunc - image_trunc.min()) / float(image_trunc.max() - image_trunc.min()) 22 | # 反转 23 | if out_inverse == 1: 24 | img_adjust = 1 - img_adjust 25 | # gamma变换 26 | img_adjust = (img_adjust**gamma)*255 27 | #!!此处有问题!!,img_adjust为浮点型0-255.0,imshow会显示不正常 28 | return img_adjust 29 | 30 | #skimage 31 | import cv2 32 | from skimage import exposure 33 | img = cv2.imread('1.jpg') 34 | gamma_img = exposure.adjust_gamma(img, gamma) 35 | #skimage像素值拉伸。若image为uint8类型,[min,max]映射到[0,255];若为float,映射到[0,1.0] 36 | exposure.rescale_intensity(image) 37 | ``` 38 | # 对数与对比度拉伸 39 | * 数学原理 40 | - 对数变换(压缩高动态范围):$log(1+f)$,$10^6$可被压缩到14 41 | ![logo](./images/log_em.PNG) 42 | - 对比度拉伸变换:$\frac{1}{(1+(m/I)^E)}$,m为灰度控制点,E控制斜率 43 | ![logo](./images/contrast.PNG) 44 | ![logo](./images/contrast_em.PNG) 45 | * MATLAB 46 | ``` 47 | %压缩高动态范围 48 | in2uint8(mat2gray(log(1+double(f)))) 49 | %对比度拉伸变换,eps防止分母为0导致溢出 50 | 1./(1+(m./(double(f)+eps)).^E) 51 | #m=mean2(f),取平均值 52 | ``` 53 | * python 54 | ```python 55 | #log-skimage 56 | from skimage import ecposure 57 | gam1= exposure.adjust_log(image) 58 | #adjust_log(image, gain=1, inv=False) 59 | #该函数在将每个像素缩放到0到1范围之后,根据方程O=gain∗log(1+I)变换输入图像像素,对于逆对数校正,该方程为O=gain∗(2^I−1) 60 | ``` 61 | ```python 62 | #对比度增强-PIL 63 | from PIL import Image 64 | from PIL import ImageEnhance 65 | #原始图像 66 | image = Image.open('lena.jpg') 67 | image.show() 68 | #亮度增强 69 | enh_bri = ImageEnhance.Brightness(image) 70 | brightness = 1.5 71 | image_brightened = enh_bri.enhance(brightness) 72 | #色度增强 73 | enh_col = ImageEnhance.Color(image) 74 | color = 1.5 75 | image_colored = enh_col.enhance(color) 76 | #对比度增强 77 | enh_con = ImageEnhance.Contrast(image) 78 | contrast = 1.5 79 | image_contrasted = enh_con.enhance(contrast) 80 | #锐度增强 81 | enh_sha = ImageEnhance.Sharpness(image) 82 | sharpness = 3.0 83 | image_sharped = enh_sha.enhance(sharpness) 84 | ``` 85 | # 直方图绘制,直方图均衡化,直方图匹配 86 | ## 绘制直方图 87 | * MATLAB 88 | ``` 89 | #介绍 90 | h = imhist(f, b) %b为灰度级个数,h(1),h(2)...代表各灰度级像素点个数 91 | h = imhist(f, b)/numel(f) %numel(f)代表f像素点个数 92 | bar(horz, v, width) #horz与v相同维度,width默认为0.8 93 | stem(horz, v, 'color_linestyle_marker', 'fill') 94 | ``` 95 | ![logo](./images/plot.PNG) 96 | ``` 97 | #绘制条形直方图案例 98 | h= imhist(f) 99 | h1= h(1:10:256) %10个灰度级为一组 100 | horz = 1:10:256 101 | bar(horz, h1) 102 | axis([0 255 0 15000]) 103 | set(gca, 'xtick', 0:50:255) #设置刻度 104 | set(gca, 'ytick', 0:2000:15000) #设置刻度 105 | xlabel('text string', 'frontsize', size) 106 | ylabel('text string', 'frontsize', size) 107 | text(xloc,yloc,'textstring', 'frontsize', size) %xloc,yloc为文字起始位置 108 | title('titlestring') 109 | #绘制杆状直方图, 也可plot 110 | h= imhist(f) 111 | h1= h(1:10:256) %10个灰度级为一组 112 | horz = 1:10:256 113 | stem(horz, h1, 'fill') 114 | axis([0 255 0 15000]) 115 | set(gca, 'xtick', 0:50:255) #设置刻度 116 | set(gca, 'ytick', 0:2000:15000) #设置刻度 117 | ``` 118 | ```python 119 | #将灰度数组映射为直方图字典,nums表示灰度的数量级 120 | def arrayToHist(grayArray, nums): 121 | w,h = grayArray.shape 122 | hist = {} 123 | for k in range(nums): 124 | hist[k] = 0 125 | for i in range(w): 126 | for j in range(h): 127 | if hist.get(grayArray[i][j]) is None: 128 | hist[grayArray[i][j]] = 0 129 | hist[grayArray[i][j]] += 1 130 | #normalize 131 | n = w*h 132 | for key in hist.keys(): 133 | hist[key] = float(hist[key])/n 134 | return hist 135 | #绘制直方图,传入的直方图要求是个字典,每个灰度对应着概率 136 | def drawHist(hist,name): 137 | keys = hist.keys() 138 | values = hist.values() 139 | x_size = len(hist)-1#x轴长度,也就是灰度级别 140 | axis_params = [] 141 | axis_params.append(0) 142 | axis_params.append(x_size) 143 | plt.figure() 144 | if name != None: 145 | plt.title(name) 146 | plt.bar(tuple(keys),tuple(values))#绘制直方图 147 | plt.show() 148 | ``` 149 | ## 直方图均衡化 150 | 灰度级均衡化处理的最终结果是一幅**扩展了动态范围**的图像,有较高的对比度 151 | * 数学原理 152 | - 建立原图像到均衡化图像的灰度级(亮度值)映射,使均衡化图像灰度级概率密度函数PDF为常数 153 | $s\epsilon[0,1]$为映射后的灰度级,r为原图像灰度级 154 | $$s=T(r)=\int_0^r p_r(w) \,{\rm d}w$$ 155 | - 证明:映射后PDF为常数 156 | 映射前后各灰度级像素个数不变,即$p_s(s)=p_r(r)\mid\frac{{\rm d}r}{{\rm d}s}\mid$ 157 | 158 | $$p_s(s)=p_r(r)\mid\frac{{\rm d}r}{{\rm d}s}\mid=p_r(r) \mid \frac{{\rm d}r}{{\rm d}T(r)}\mid$$ 159 | $$=p_r(r)|\frac{{\rm d}}{{\rm d}T(r)} \int_0^r p_r(w) \,{\rm d}w |=1$$ 160 | 161 | - 对于离散值$p_r(r_k)=\frac{n_k}{n}$ 162 | $$s_k=T(r_k)=\sum_{j=0}^k p_r(r_j)=\sum_{j=0}^k \frac{n_j}{n} $$ 163 | $$k=0,1,2,...,L-1$$ 164 | * MATLAB 165 | ``` 166 | g=histeq(f, nlev) %nlev为输出图像的灰度级数 167 | ``` 168 | ``` 169 | %绘制映射函数 170 | hnorm= imhist(f)./numel(f) 171 | cdf= cumsum(hnrom) 172 | x= linespace(0,1,256) 173 | plot(x, cdf) 174 | ``` 175 | * python 176 | ```python 177 | #计算累计直方图计算出新的均衡化的图片,h_s为计算好的直方图灰度级数组,nums为灰度数,256 178 | def equalization(grayArray, h_s,nums): 179 | #计算累计直方图 180 | tmp = 0.0 181 | h_acc = h_s.copy() 182 | for i in range(256): 183 | tmp += h_s[i] 184 | h_acc[i] = tmp 185 | if len(grayArray.shape) != 2: 186 | print("length error") 187 | return None 188 | w,h = grayArray.shape 189 | des = np.zeros((w,h),dtype = np.uint8) 190 | for i in range(w): 191 | for j in range(h): 192 | des[i][j] = int((nums - 1)* h_acc[grayArray[i][j] ] +0.5) 193 | return des 194 | ``` 195 | ## 直方图匹配 196 | 当累计变换函数非常陡,即灰度级过于集中,直方图均衡化将失效;直方图匹配的结果则是我们指定的直方图,由于原始图像的累计直方图和我们指定的输出图片的直方图的累计直方图不可能完全相同,所以匹配结果并非百分之百的匹配。 197 | * 数学原理 198 | 使两个累积概率函数尽可能相似 199 | * MATLAB 200 | ``` 201 | g= histeq(f, hspec) %hspec为指定的直方图;当hspec灰度级数远小于f中时,能较好的匹配 202 | %双峰值高斯函数模拟直方图,A为双峰权值;k用于提高直方图下限 203 | function p= two_mode_gauss(m1, sig1, m2, sig2, A1, A2, k) 204 | c1= A1 * (1/((2*pi)^0.5)*sig1) 205 | k1= 2* sig1^2 206 | c2= A2 * (1/((2*pi)^0.5)*sig2) 207 | k2= 2* sig2^2 208 | z= linspace(0,256,256) 209 | p= k+ c1*exp(-((z-m1).^2)./k1) + c2*exp(-((z-m2).^2)./k2) 210 | p= p./sum(p(:)) 211 | ``` 212 | * python 213 | ```python 214 | #直方图匹配函数,接受原始图像grayArray和目标灰度直方图h_d 215 | def histMatch(grayArray,h_d): 216 | #计算累计直方图 217 | tmp = 0.0 218 | h_acc = h_d.copy() 219 | for i in range(256): 220 | tmp += h_d[i] 221 | h_acc[i] = tmp 222 | h1 = arrayToHist(grayArray,256) 223 | tmp = 0.0 224 | h1_acc = h1.copy() 225 | for i in range(256): 226 | tmp += h1[i] 227 | h1_acc[i] = tmp 228 | #计算映射 229 | M = np.zeros(256) 230 | for i in range(256): 231 | idx = 0 232 | minv = 1 233 | for j in h_acc: 234 | if np.fabs(h_acc[j] - h1_acc[i]) < minv: 235 | minv = np.fabs(h_acc[j] - h1_acc[i]) 236 | idx = int(j) 237 | M[i] = idx 238 | des = M[grayArray] 239 | return des 240 | ``` 241 | # 空间滤波 242 | ## 线性滤波 243 | Q:相关与卷积??有什么案例能说明,二者对试验结果的影响? 244 | * MATLAB 245 | - 生成滤波器 246 | `w = fspecial('type', parameters)` 247 | ![logo](./images/fspecial.PNG) 248 | ![logo](./images/laplac.PNG) 249 | - 滤波,w为掩膜,w=[1 1 1; 1 -8 1; 1 1 1] 250 | `g=imfilter(f, w, filtering_mode, boundary_option, size_option)` 251 | ![logo](./images/imfilter.PNG) 252 | * python 253 | ```python 254 | #用到再去找 255 | #blur—图像均值平滑滤波src:图像矩阵;ksize:滤波窗口尺寸 256 | cv2.blur(src, ksize, dst=None, anchor=None, borderType=None) 257 | #GaussianBlur—图像高斯平滑滤波;src:图像矩阵;ksize:滤波窗口尺寸;sigmaX:标准差 258 | cv2.GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None) 259 | #laplace 260 | kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) 261 | dst = cv2.filter2D(img, -1, kernel=kernel) 262 | #Sobel函数 263 | cv2.Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None) 264 | #前四个是必须的参数:src是需要处理的图像;ddepth是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;第三和第四:dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。 265 | ``` 266 | ## 非线性滤波 267 | * MATLAB 268 | - 最佳选择colfilt 269 | colfilt占用更多内存,但比nlfilter快得多。 270 | - 填充函数padarray 271 | 272 | - ordfilt2生成统计排序滤波器 273 | * python 274 | ```python 275 | #medianBlur—图像中值滤波;src:图像矩阵;ksize:滤波窗口尺寸 276 | cv2.medianBlur(src, ksize, dst=None) 277 | ``` 278 | 279 | 280 | -------------------------------------------------------------------------------- /CH03/imadjust_test.py: -------------------------------------------------------------------------------- 1 | from skimage import io,exposure 2 | import numpy as np 3 | import cv2 4 | 5 | 6 | def imadjust(img_mono, gamma, low_in=0, high_in=255, out_inverse=0): 7 | # img_mono单通道图像,[low_in,high_in]到[0,1]映射,out_inverse=1时为到[1,0]的映射 8 | # 将[low_in,high_in]以外值减掉,向量化 9 | image_trunc = (img_mono > high_in) * high_in + (img_mono <= high_in) * img_mono 10 | # cv2.imshow('temp', image_trunc) 11 | image_trunc = (image_trunc < low_in) * low_in + (image_trunc >= low_in) * image_trunc 12 | # 归一化0-1 13 | img_adjust = (image_trunc - image_trunc.min()) / float(image_trunc.max() - image_trunc.min()) 14 | # 反转 15 | if out_inverse == 1: 16 | img_adjust = 1 - img_adjust 17 | # gamma变换 18 | img_adjust = (img_adjust**gamma) 19 | return img_adjust 20 | 21 | 22 | img = cv2.imread('./images/gamma.PNG') 23 | img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 24 | 25 | cv2.imshow('src', img_gray) 26 | img_ad = imadjust(img_gray, 1, 0, 255, 0) 27 | cv2.imshow('after', img_ad) 28 | cv2.waitKey(0) 29 | 30 | -------------------------------------------------------------------------------- /CH03/images/contrast.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/contrast.PNG -------------------------------------------------------------------------------- /CH03/images/contrast_em.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/contrast_em.PNG -------------------------------------------------------------------------------- /CH03/images/fspecial.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/fspecial.PNG -------------------------------------------------------------------------------- /CH03/images/gamma.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/gamma.PNG -------------------------------------------------------------------------------- /CH03/images/imfilter.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/imfilter.PNG -------------------------------------------------------------------------------- /CH03/images/laplac.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/laplac.PNG -------------------------------------------------------------------------------- /CH03/images/log_em.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/log_em.PNG -------------------------------------------------------------------------------- /CH03/images/plot.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH03/images/plot.PNG -------------------------------------------------------------------------------- /CH06/chapter6.md: -------------------------------------------------------------------------------- 1 | # 彩色图像处理 2 | ## 索引图像 3 | * 概念 4 | 一幅索引图包含一个数据矩阵data和一个调色板矩阵map,数据矩阵可以是uint8,uint16或双精度类型的,而调色板矩阵则总是一个m×3的双精度矩阵 5 | 索引图像相比彩色图像,文件更小,主要用于网络上的图片传输和一些对图像像素、大小等有严格要求的地方 6 | `imshow(X, copper)`,copper为MATLAB内置彩色映射 7 | ![logo](./images/colormap.PNG) 8 | * 图像“抖动”(用黑白二值图产生灰色调) 9 | `bw= dither(gray_img)`%灰度图转换为二值“抖动”图 10 | `rgb2ind`对减少RGB图像的色彩数很有用 11 | ![logo](./images/rgb_ind_gray.PNG) 12 | 13 | ## 图像基本操作 14 | * 分离通道&合并通道 15 | - MATLAB 16 | 17 | ``` 18 | rgb_img= cat(3, fR, fG, fB) 19 | fR = rgb_img(:,:,1) 20 | fG = rgb_img(:,:,2) 21 | fB = rgb_img(:,:,3) 22 | %rgbcube(vx,vy,vz),绘制彩色立方体 23 | ``` 24 | - python 25 | 26 | ```python 27 | B,G,R = cv2.split(image) 28 | img = cv2.merge([B,G,R]) 29 | ``` 30 | * 色彩空间转换 31 | - 颜色空间类型 32 | NTSC,YCbCr,HSV,CMYK,HSI 33 | - MATLAB 34 | 35 | ``` 36 | hsv_img= rgb2hsv(rgb_img) 37 | rgb_img= hsv2rgb(hsv_img) 38 | cmy_img= imcomplement(rgb_img) 39 | rgb_img= imcomplement(cmy_img) 40 | ``` 41 | - python 42 | 43 | ```python 44 | #skimage 45 | skimage.color.rgb2grey(rgb) 46 | skimage.color.rgb2hsv(rgb) 47 | skimage.color.rgb2lab(rgb) 48 | skimage.color.gray2rgb(image) 49 | skimage.color.hsv2rgb(hsv) 50 | skimage.color.lab2rgb(lab) 51 | #opencv 52 | cv2.cvtColor(input_image,flag) 53 | #flag:cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV.... 54 | ``` 55 | 56 | ## 彩色变换 57 | * 生成映射函数 58 | - `z=interplq(x,y,xi)`:`z=interplq([0 255]' [0 255]' [0:255]')` 59 | - `z=spline(x,y,xi)` :若y比x多两个元素,则第一个和最后一个被假定为三次样条的端滚降 60 | - `g=ice('image',f,'space','hsi')`:鼠标控制映射曲线 61 | ![logo](./images/ice.PNG) 62 | * 彩色图均衡化 63 | RGB分量分别均衡化会导致错误的色彩,转换为HSI后,H不动(色调保持不变),S、I进行均衡化。 64 | 65 | ## 彩色图像空间滤波 66 | * 平滑-在RGB独立分量上同时进行 67 | ``` 68 | %MATLAB 69 | w=fspecial('average',25) 70 | I_filter=imfilter(I,w,'replicate') 71 | ``` 72 | * 锐化-在RGB独立分量上同时进行 73 | ``` 74 | %MATLAB 75 | mask=[1 1 1;1 -8 1;1 1 1] 76 | fen=imsubstract(fb,imfilter(fb,mask,'replicate')) 77 | ``` 78 | 79 | ## RGB向量空间直接处理 80 | 基于单独彩色平面的处理不等于直接在RGB向量空间中处理 81 | * 使用梯度的彩色边缘检测 82 | - 灰度图像梯度 83 | 84 | 二维函数$f(x,y)$的梯度向量为$\nabla f= [G_x G_y]^T=[\frac{\partial f}{\partial x} \frac{\partial f}{\partial y}]^T$ 85 | 梯度向量幅值为$mag(\nabla f)=[{G_x}^2+{G_y}^2]^{1/2}=[{\frac{\partial f}{\partial x}}^2+{\frac{\partial f}{\partial y}}^2]^{1/2}$ 86 | 使用近似值避免平方与开平方运算(幅度与变化程度成比例)$ mag(\nabla f) \approx|G_x|+|G_y|$。 87 | $G_x$等导数用邻域内的像素值差来计算 88 | ![logo](./images/G_x.PNG) 89 | 最大梯度角度$\alpha(x,y)=arctan(\frac{G_y}{G_x})$ 90 | - 彩色空间计算梯度 91 | 将这三个通道的信息看作是一个矢量,而矢量是不存在梯度的概念的,我们无法直接将上诉方法或算子直接用于RGB 图像,而且RGB图像单个通道的梯度信息又无法反映整体的梯度信息。 92 | - 彩色空间梯度推导 93 | 在多通道图像中,假设梯度方向为$\theta$ 94 | $$\nabla f = ||f(x+\varepsilon cos\theta, y+\varepsilon sin\theta)||$$ 95 | 为了便于计算,将计算绝对值换为计算平方,令 96 | $$\nabla f^2 = ||f(x+\varepsilon cos\theta, y+\varepsilon sin\theta)||^2$$ 97 | 对$f(x+\varepsilon cos\theta, y+\varepsilon sin\theta)$进行二次泰勒展开: 98 | $$f(x+\varepsilon cos\theta, y+\varepsilon sin\theta)=f(x,y)+\sum_{i=1}^m (\varepsilon cos\theta \cdot \frac{\partial f_i(x,y)}{\partial x}+\varepsilon sin\theta \cdot \frac{\partial f_i(x,y)}{\partial y})+o^n$$ 99 | $$\approx f(x,y)+\sum_{i=1}^m (\varepsilon cos\theta \cdot \frac{\partial f_i(x,y)}{\partial x}+\varepsilon sin\theta \cdot \frac{\partial f_i(x,y)}{\partial y})$$ 100 | 其中$m$表示图像通道数,为方便表述,用$\frac{\partial f_i}{\partial x}$代替$\frac{\partial f_i(x,y)}{\partial x}$,则有: 101 | $$\nabla f^2 = \sum_{i=1}^m (\varepsilon cos\theta \cdot \frac{\partial f_i}{\partial x}+\varepsilon sin\theta \cdot \frac{\partial f_i}{\partial y})^2$$ 102 | 重新定义函数$G(\theta)$,令 103 | $$G(\theta)= \sum_{i=1}^m (\varepsilon cos\theta \cdot \frac{\partial f_i}{\partial x}+\varepsilon sin\theta \cdot \frac{\partial f_i}{\partial y})^2$$ 104 | $$=\varepsilon^2 (cos\theta^2 \cdot \sum_{i=1}^m||\frac{\partial f_i}{\partial x}||^2+sin\theta^2 \cdot \sum_{i=1}^m||\frac{\partial f_i}{\partial y}||^2+2sin\theta cos\theta \sum_{i=1}^m \frac{\partial f_i}{\partial x} \frac{\partial f_i}{\partial y})$$ 105 | 因为要求$G(\theta)$最大值,$\varepsilon$无用,舍去 106 | $$G(\theta)=cos\theta^2 \cdot \sum_{i=1}^m||\frac{\partial f_i}{\partial x}|^2|+sin\theta^2 \cdot \sum_{i=1}^m||\frac{\partial f_i}{\partial y}||^2+2sin\theta cos\theta \sum_{i=1}^m \frac{\partial f_i}{\partial x} \frac{\partial f_i}{\partial y}$$ 107 | 为了进一步方便表述;令 108 | $$E=\sum_{i=1}^m||\frac{\partial f_i}{\partial x}||^2; F=\sum_{i=1}^m||\frac{\partial f_i}{\partial y}||^2; H=\sum_{i=1}^m \frac{\partial f_i}{\partial x} \frac{\partial f_i}{\partial y}$$ 109 | $$G(\theta)=cos\theta^2 E + sin\theta^2 F + 2sin\theta cos\theta H$$ 110 | 边缘的方向是图像像素梯度最大的方向。也就是说梯度的方向\theta_max会使G(\theta)取最大值,则; 111 | $$\theta_max=\mathop{G(\theta)}\limits_{argmax}$$ 112 | 对$G(\theta)$进行求导 113 | $$G(\theta)'=-Ecos(2\theta)+2Fcos(2\theta)+Hsin(2\theta)$$ 114 | 令$G(\theta)'=0$,可得: 115 | $$tan(2\theta_max)=\frac{2F}{E-H}$$ 116 | $$\theta_max=\frac{1}{2}arctan(\frac{2F}{E-H}+k\pi)$$ 117 | 很明显$G(\theta )$是一个以\pi为周期的周期函数,如果只考虑区间$\left [ 0 ,\pi\right )[0,π)$,且$\theta_{max}$落到该区间内,则会有另一个让$G(\theta )$取极值的解也落在该区域内, 118 | 这个值是$\theta_{max}+ \frac{\pi}{2}$或者$\theta_{max}-\frac{\pi}{2}$。但是不论如何这两个解有一个让$G(\theta )$取极大值,另一个让其取极小值,两个角度相差 90°。 119 | - 应用计算 120 | 设$\vec r,\vec g, \vec b$分别是RGB彩色空间定义向量,并定义向量 121 | $$\vec u = \frac{\partial R}{\partial x} \vec r + \frac{\partial G}{\partial x} \vec g + \frac{\partial B}{\partial x} \vec b$$ 122 | $$\vec v = \frac{\partial R}{\partial y} \vec r + \frac{\partial G}{\partial y} \vec g + \frac{\partial B}{\partial y} \vec b$$ 123 | $g_xx,g_yy,g_xy$是这些向量的点积: 124 | $$g_xx= \vec u \cdot \vec u =\vec u^T \vec u =|\frac{\partial R}{\partial x}|^2+|\frac{\partial G}{\partial x}|^2 +|\frac{\partial B}{\partial x}|^2$$ 125 | $$g_xx= \vec v \cdot \vec v =\vec v^T \vec v =|\frac{\partial R}{\partial y}|^2+|\frac{\partial G}{\partial y}|^2 +|\frac{\partial B}{\partial y}|^2$$ 126 | $$g_xx= \vec u \cdot \vec v =\vec u^T \vec v =\frac{\partial R}{\partial x}\frac{\partial R}{\partial y}+\frac{\partial G}{\partial x}\frac{\partial G}{\partial y} +\frac{\partial B}{\partial x}\frac{\partial B}{\partial y}$$ 127 | 梯度方向角: 128 | $$\theta(x,y)=\frac{1}{2}arctan[\frac{2g_xy}{g_xx-g_yy}]$$ 129 | 梯度值: 130 | $$F_\theta(x,y)=\{ \frac{1}{2}[(g_xx+g_yy)+(g_xx-g_yy)cos2\theta+2g_xy sin2\theta\}]^{1/2}$$ 131 | - MATLAB 132 | 133 | ``` 134 | [VG, A, PPG]= colorgrad(f,T) 135 | ``` 136 | 其中,f是RGB图像,T是[0,1]范围内的阈值选项(默认为0); 137 | VG是RGB向量梯度$F_\theta(x, y)$;A是以弧度计的角度$\theta(x, y)$,并且PPG是由单独彩色平面的2D梯度之和形成的梯度图像。 138 | 计算上述方程时,要求全部微分都可用函数clorgrad中的Sobel算子来实现。输出VG和PPG通过clorgrad被归一化到[0, 1]范围内,并且把它们作为阈值进行处理。所以,它们的值小于或等于T,VG(x,y)=0;对于其他的情况,$VG(x,y) = VG(x,y)$。 139 | ![logo](./images/colorgrad.PNG) 140 | - python 141 | Q:!!!没有彩色图像梯度?都是sobel与laplacian 142 | * RGB向量空间中的图像分割 143 | - 距离度量(计算相似度) 144 | - 欧几里得距离 145 | $$D(\vec z,\vec m)=||\vec z - \vec m||=[(\vec z - \vec m)^T(\vec z - \vec m)]^{1/2}$$ 146 | - 马氏距离(mahalanobis) 147 | $$D(\vec z,\vec m)=[(\vec z - \vec m)^T C^{-1}(\vec z - \vec m)]^{1/2}$$ 148 | C是要分割的彩色样值表示的协方差矩阵。马氏距离一个三维椭圆体,重要属性是主轴取在最大数据扩展方向上。 149 | ![logo](./images/mahalabis.PNG) 150 | **马氏距离与尺度无关** 151 | 如果是单纯使每个变量先标准化,然后再计算距离,可能会出现某种错误,原因是可能在有些多维空间中,某个两个维之间可能是线性相关的。 152 | 通过对线性无关的分量进行标准化后,再求得距离是合理的。 153 | mahalanobis距离是基于样本分布的一种距离。物理意义就是在规范化的主成分空间中的欧氏距离。 154 | 它的缺点是夸大了变化微小的变量的作用。 155 | - 马氏距离推导 156 | - 基本思想 157 | 如下图的过程(以两个维度作为例子),此例的数据重心为原点,P1,P2到原点的欧氏距离相同,但点P2在y轴上相对原点有较大的变异,而点P1在x轴上相对原点有较小的变异。所以P1点距原点的直观距离是比P2点的小的。 158 | 159 | ![logo](./images/mahalobis/1.PNG) 160 | 马氏距离就是解决这个问题,它将直观距离和欧式距离统一。为了做到这一点, 它先将数据不同维度上的方差统一(即各维度上的方差相同),此时的欧式距离就是直观距离。 161 | 如下图:统一方差后的图,P1^到原点的距离小于P2^。P1到原点的欧式距离和P2的相同。以上所说的直观距离就是马氏距离。 162 | 163 | ![logo](./images/mahalobis/2.PNG) 164 | 但是,如果不同维度之间具有相关性,则压缩的效果就不好了。如下图只在横向和纵向上压缩,则达不到上图的压缩效果。所以在F1方向和F2方向上压缩数据才能达到较好的效果。所以需要将原始数据在XY坐标系中的坐标 表示在F坐标系中。然后再分别沿着坐标轴压缩数据。 165 | 166 | ![logo](./images/mahalobis/3.PNG) 167 | 所以,计算样本数据的马氏距离分为两个步骤:1、坐标旋转;2、数据压缩 168 | **坐标旋转的目标**:使旋转后的各个维度之间线性无关,所以该旋转过程就是主成分分析的过程。 169 | **数据压缩的目标**:所以将不同的维度上的数据压缩成为方差都是1的的数据集。 170 | - 理论推导 171 | 有一个原始的多维样本数据$X_{n*m}$(m列,n行): 172 | $$ 173 | \begin{matrix} 174 | x_{11} & x_{12} & \cdots & x_{1m}\\ 175 | x_{21} & x_{22} & \cdots & x_{2m}\\ 176 | \vdots & \vdots & \ddots & \vdots \\ 177 | x_{n1} & x_{n2} & \cdots & x_{nm} 178 | \end{matrix} 179 | $$ 180 | 其中每一行表示一个测试样本(共n个);$X_i$表示样本的第i个维度(共m个)。$X_i=(x_{1i},x_{2i},…,x_{ni})^T$ ,以上多维样本数据记为$X=(X_1,X_2⋯X_m)$。样本的总体均值为$\mu_X=(\mu_{X1},\mu_{X2}⋯\mu_{Xm})$。其协方差为: 181 | $$\sum X=E{(X−\mu_X)^T(X−\mu_X)}=\frac{1}{n}(X−\mu_X)^T(X−\mu_X)$$ 182 | 协方差矩阵表示样本数据各维度之间的关系的。其中n是样本的数量。 183 | 将原始数据集X通过坐标旋转矩阵U旋转到新的坐标系统中得到一个各变量线性无关的新的数据集F。 184 | $$F^T = (F_1,F_2 \cdot F_m)^T = UX^T \tag{(1)}$$ 185 | 新数据集F的均值记为$\mu_F=(\mu_{F_1},\mu_{F_2}⋯\mu_{F_m}), \mu_F=U\mu_X \tag{(2)}$ 186 | 由公式$(1)(2)$可知:$(F−\mu_F)=(X−\mu_X)U^T \tag{(3)}$ 187 | 由于F的各维度之间是不相关的,所以新数据集F的协方差矩阵\sum_F应该为对角阵,由公式$(3)$可得: 188 | $${\sum}_F = E{(F−\mu_F)^T (F−\mu_F)}= \frac{1}{n}(F−\mu_F)^T (F−\mu_F)$$ 189 | $$=\frac{1}{n} U(X−\mu_X)^T(X−\mu_X)U^T =U {\sum}_X U^T= 190 | \left[ 191 | \begin{matrix} 192 | \lambda_1 & & & \\ 193 | & \lambda_2 & & \\ 194 | & & \ddots & \\ 195 | & & & \lambda_m 196 | \end{matrix} 197 | \right] 198 | $$ 199 | 可以看出,其中$X$数据的协方差的根号特征值 $\sqrt{\lambda_i}$ 就是$F$数据中第i个维度的方差。U为$\sum_X$的特征向量构成的正交矩阵 $U^T=U^{−1}$。 200 | 将不同的维度上的数据压缩成为方差都是1,以下推导马氏距离公式: 201 | $$d^2(f,\mu_F)= (\frac{F_1-\mu_{F_1}}{\sqrt{\lambda_1}})^2+(\frac{F_2-\mu_{F_2}}{\sqrt{\lambda_2}})^2+ \cdot +(\frac{F_m-\mu_{F_m}}{\sqrt{\lambda_m}})^2$$ 202 | $$=(F_1−\mu_{F_1},F_2−\mu_{F_2}⋯ F_m−\mu_{F_m}) 203 | \left[\begin{matrix} 204 | \frac{1}{\lambda_1} & & & \\ 205 | & \frac{1}{\lambda_2} & & \\ 206 | & & \ddots & \\ 207 | & & & \frac{1}{\lambda_m } 208 | \end{matrix}\right] 209 | (F_1−\mu_{F_1},F_2−\mu_{F_2}⋯ F_m−\mu_{F_m})^T $$ 210 | $$=(F−\mu_F)(U {\sum}_X U^T)^{−1}(F−\mu_F)^T=(X−\mu_X)U^T(U{\sum}_X U^T)^{−1} U(X−\mu_X)^T = (X−\mu_X) {\sum}_X^{−1} (X−\mu_X)^T$$ 211 | 212 | - MATLAB 213 | - 函数 214 | ![logo](./images/colorseg1.PNG) 215 | ![logo](./images/colorseg2.PNG) 216 | - 案例 217 | 218 | ``` 219 | mask= roipoly(f); %交互式确定感兴趣区域 220 | red= immuliply(mask, f(:,:,1)); 221 | green= immuliply(mask, f(:,:,2)); 222 | blue= immuliply(mask, f(:,:,3)); 223 | g = cat(3, red, green, blue); 224 | %计算均值向量与协方差矩阵 225 | [M N K] = size(g) 226 | I = reshape(g, M*N, 3) 227 | idx = find(mask) 228 | I = double(I(idx, 1:3)) 229 | [C, m] = covmatrix(I) %求协方差矩阵与均值向量 230 | %d = diag(C) 231 | %sd = sqrt(d) 232 | E25 = colorseg('mahalanobis',f,25,m) 233 | ``` 234 | 235 | 236 | -------------------------------------------------------------------------------- /CH06/images/G_x.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/G_x.PNG -------------------------------------------------------------------------------- /CH06/images/colorgrad.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/colorgrad.PNG -------------------------------------------------------------------------------- /CH06/images/colormap.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/colormap.PNG -------------------------------------------------------------------------------- /CH06/images/colorseg1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/colorseg1.PNG -------------------------------------------------------------------------------- /CH06/images/colorseg2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/colorseg2.PNG -------------------------------------------------------------------------------- /CH06/images/ice.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/ice.PNG -------------------------------------------------------------------------------- /CH06/images/mahalabis.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/mahalabis.PNG -------------------------------------------------------------------------------- /CH06/images/mahalobis/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/mahalobis/1.PNG -------------------------------------------------------------------------------- /CH06/images/mahalobis/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/mahalobis/2.PNG -------------------------------------------------------------------------------- /CH06/images/mahalobis/3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/mahalobis/3.PNG -------------------------------------------------------------------------------- /CH06/images/rgb_ind_gray.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH06/images/rgb_ind_gray.PNG -------------------------------------------------------------------------------- /CH09/chapter9.md: -------------------------------------------------------------------------------- 1 | # 形态学图像处理 2 | ## 二值图像集合运算 3 | ![logo](./images/set_operate.PNG) 4 | ## 膨胀和腐蚀 5 | ### 膨胀 6 | * 原理 7 | 数学上,膨胀定义为集合运算。A被B膨胀,记为 8 | $$ A\oplus B=\{z|(\hat{B})_z \cap A \neq \emptyset\} $$ 9 | 其中,B为结构元素,$\hat{B}$为B的映像,定义为$\hat{B}=\lbrace \omega|\omega=-b,b\epsilon B \rbrace$。 10 | $(B)_z$为点$z=(z_1,z_2)$对集合B的平移运算,定义为$(B)_z=\lbrace c|c=b+z,b\epsilon B \rbrace$ 11 | 总之,$A \oplus B$是所有结构元素原点位置组成的集合,其中映射并平移后的B至少与A的某些部分重叠。 12 | ![logo](./images/struct_yuansu.PNG) 13 | * MATLAB 14 | 15 | ``` 16 | A = imread('broken_text.tif') 17 | B = [ 0 1 0;1 1 1;0 1 0 ] 18 | A2=imdilate(A,B) 19 | ``` 20 | ![logo](./images/imdilate.PNG) 21 | * 结构元素的分解 22 | 膨胀满足结合律,即:$A\oplus(B \oplus C)=(A \oplus B)\oplus C$ 23 | 假设构造元素B可以表示为两个构造元素$B_1$和$B_2$的膨胀,即:$B=B_1\oplus B_2$,则$A\oplus B=(A\oplus B_1)\oplus B_2$ 24 | ![logo](./images/seperate.PNG) 25 | 原始构造元素中的元素为25,分解后只有10个,运算速度快2.5倍。??不对吧,分解后的第二次膨胀不是5x5?? 26 | * 函数strel构造结构元素 27 | ![logo](./images/strel.PNG) 28 | 除了可以生成结构元素,strel还可以以分解形式产生结构元素。imdilate将自动使用分解信息加快膨胀处理。 29 | 函数`decomp=getsequence(se);decomp(1)`可用于提取并检查分解中的单个结构元素 30 | ### 腐蚀 31 | * 原理 32 | 腐蚀的数学定义与膨胀相似,A被B腐蚀即为$A\ominus B$,定义为 33 | $$ A \ominus B=\lbrace z|(\hat{B})_z \cap A^c \neq \emptyset \rbrace $$ 34 | * MATLAB 35 | ``` 36 | A=imrode(A, se) 37 | ``` 38 | * python 39 | ```python 40 | #设置卷积核5*5 41 | kernel = np.ones((5,5),np.uint8) 42 | #图像的腐蚀,默认迭代次数 43 | erosion = cv2.erode(src,kernel) 44 | #图像的膨胀 45 | dst = cv2.dilate(erosion,kernel) 46 | ``` 47 | ## 腐蚀和膨胀的组合 48 | ### 开运算和闭运算 49 | 开运算使二值图中细小连接部分断开(去除杂点),闭运算使二值图中缺口被填补。 50 | ![logo](./images/open_close.PNG) 51 | 可对图像先开运算,去除杂点;再闭运算,填补缺口,增强连接。 52 | ![logo](./images/zhiwen.PNG) 53 | * 开运算 54 | A被B的形态学开运算可以记做$A\circ B$,是A被B腐蚀再用B来膨胀的结果: 55 | $$A\circ B=(A\ominus B)\oplus B=\cup{(B)_z|(B)_z\subseteq A}$$ 56 | $A\circ B$可理解为,B在A内完全匹配的平移的并集。 57 | * 闭运算 58 | $$ A\bullet B=(A\oplus B)\ominus B $$ 59 | * MATLAB 60 | ``` 61 | C=imopen(A,B) 62 | C=imclose(A,B) 63 | ``` 64 | * python 65 | ```python 66 | kernel = np.ones((5,5),np.uint8) 67 | closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) 68 | opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 69 | #图像的膨胀和腐蚀之间的差异,结果看起来像目标的轮廓 70 | gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) 71 | ``` 72 | ### 击中或击不中变换 73 | 用于识别特定形状(线段端点、),B为结构元素$B=(B_1, B_2)$ 74 | $$A\otimes B = (A\ominus B_1)\cap(A^c\ominus B_2)$$ 75 | 可理解为,输出图像由$B_1$中匹配的像素(被击中)和同时未被$B_2$匹配的像素组成 76 | ``` 77 | %MATLAB 78 | B1=strel([0 0 0;0 1 1;0 1 0])%定位东、南邻域的像素 79 | B2=strel([1 1 1;1 0 0;1 0 0]) 80 | g=bwhitmiss(f, B1, B2) 81 | ``` 82 | ### 使用查找表 83 | 选用击中或击不中变换的较快方法是使用查找表(LUT),将所有结构元素($2^9=512$个$3*3$的patch)储存在表中, 84 | 索引为patch与下面矩阵的点乘,然后把所有加起来。该过程得到的索引为在范围[0,511]中的唯一一个值。 85 | $$ 86 | \begin{matrix} 87 | 1 & 8 & 64\\ 88 | 2 & 16 & 128 \\ 89 | 4 & 32 & 256 90 | \end{matrix} 91 | $$ 92 | ### 顶帽与黑帽 93 | * 图像顶帽(或图像礼帽)运算是原始图像减去图像开运算的结果,得到图像的噪声。如下图所示: 94 | 顶帽运算(img) = 原始图像(img) - 开运算(img) 95 | 可以看到外部噪声被提取出来 96 | * 图像黑帽运算是图像闭运算操作减去原始图像的结果,得到图像内部的小孔,或者前景色中的小黑点。如下图所示: 97 | 黑帽运算(img) = 闭运算图像(img) - 原始图像(img) 98 | 可以看到图像内部黑点被提取出来 99 | ![logo](./images/hat.PNG) 100 | * python 101 | ```python 102 | #创建特殊构造元素,MORPH_RECT矩形,MORPH_ELLIPSE椭圆,MORPH_CROSS十字 103 | kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) 104 | #顶帽 105 | kernel = np.ones((5,5),np.uint8) 106 | tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) 107 | #黑帽 108 | blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) 109 | ``` 110 | ### MATLAB IPT函数bwmorph 111 | 可用于膨胀、腐蚀、查找表操作的组合,实现许多有用的操作 112 | ![logo](./images/morph.PNG) 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /CH09/images/hat.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/hat.PNG -------------------------------------------------------------------------------- /CH09/images/imdilate.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/imdilate.PNG -------------------------------------------------------------------------------- /CH09/images/morph.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/morph.PNG -------------------------------------------------------------------------------- /CH09/images/open_close.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/open_close.PNG -------------------------------------------------------------------------------- /CH09/images/seperate.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/seperate.PNG -------------------------------------------------------------------------------- /CH09/images/set_operate.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/set_operate.PNG -------------------------------------------------------------------------------- /CH09/images/strel.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/strel.PNG -------------------------------------------------------------------------------- /CH09/images/struct_yuansu.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/struct_yuansu.PNG -------------------------------------------------------------------------------- /CH09/images/zhiwen.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH09/images/zhiwen.PNG -------------------------------------------------------------------------------- /CH10/chapter10.md: -------------------------------------------------------------------------------- 1 | # 图像分割 2 | ## 点、线和边缘检测 3 | 点、线和边缘是亮度不连续的三种基本类型。**用于查找不连续的最常用方法**是空间滤波。掩膜在一点处的响应为: 4 | $$R= \omega_1 z_1 + \omega_2 z_2 + \cdots + \omega_9 z_9 = \sum_{i=1}^9 \omega_i z_i$$ 5 | ### 点检测 6 | * 空间滤波检测 7 | 点检测模板为:$[-1,-1,-1;-1,8,-1;-1,-1,-1]$ 8 | 9 | - MATLAB 10 | 11 | ``` 12 | w = [-1,-1,-1;-1,8,-1;-1,-1,-1] 13 | g = abs(imfilter(double(f),w)) 14 | T = max(g(:)) %阈值设为最大值,只提取最大响应点 15 | g = g>=T 16 | ``` 17 | 18 | * 领域排序检测 19 | 将$m*n$的邻域中左右像素值进行排序,如果这些点最大值与最小值之差超过了T,则判断为有点区域,可把最大值作为点。 20 | - MATLAB 21 | 22 | ``` 23 | %函数ordfilt2为分线性滤波函数,可用于排序 24 | g= imsubtract(ordfilt2(f, m*n, ones(m,n)),... ordfilt2(f, 1, ones(m,n))) 25 | g= g>=T 26 | %可用m*n-1替代最右端的1,从而得到最高像素值和第二高像素值的差值。 27 | ``` 28 | 29 | ### 线检测 30 | * 空间滤波检测 31 | 以下滤波核分别在水平线、+45°线、垂直线、-45°线响应最大。每个掩膜系数之和为0,表明亮度不变区域响应为0。 32 | ![logo](./images/line.PNG) 33 | 提取的边缘只有单个像素宽度,应同时使用点检测模板,删除孤立点。 34 | * 一阶/二阶导数检测 35 | 基本原则:1、找到亮度的一阶导数在幅度上比指定的阈值大的地方;2、找到亮度的二阶导数(拉普拉斯算子)有零交叉的地方。 36 | - MATLAB—edge函数进行边缘检测 37 | 梯度$g=({G_x}^2+{G_y}^2)^2$ 38 | 39 | ``` 40 | [g,t]= edge(f, 'method'. parameters) %基本语法 41 | %g为0,1逻辑数组,t为edge函数使用的阈值,‘method’为表10.1中的方法,parameters根据method不同而变化 42 | [g,t]= edge(f, 'sobel'. T, dir) %sobel。dir为指定检测首选方向:'horizontal','vertical','both' 43 | [g,t]= edge(f, 'prewitt'. T, dir) %prewitt 44 | [g,t]= edge(f, 'roberts'. T, dir) %roberts 45 | [g,t]= edge(f, 'log'. T, sigma) %LoG 46 | [g,t]= edge(f, 'zerocross'. T, H) %零交叉。H为指定的滤波函数 47 | [g,t]= edge(f, 'canny'. T, sigma) %canny。T=[T1, T2] 48 | ``` 49 | 50 | ![logo](./images/edge.PNG) 51 | ![logo](./images/suanzi.PNG) 52 | - LoG(高斯拉普拉斯)检测器 53 | 高斯函数$h(r)=-e^{-\frac{r^2}{2\sigma^2}}$,其中$r^2=x^2 +y^2$。与图像卷积将会变模糊。 54 | 该函数的拉普拉斯算子为$\nabla h(r)= -(\frac{r^2-\sigma^2}{\sigma^4}) e^{-\frac{r^2}{2\sigma^2}}$ 55 | 使用LoG将产生两个效果:1、使图像平滑。2、计算拉普拉斯算子,以产生双边缘图像。 56 | 57 | ```python 58 | import cv2 59 | #只有laplacian 60 | img = cv2.imread('test.jpg') 61 | #对彩色图 62 | gray_lap = cv2.Laplacian(img,cv2.CV_16S,ksize = 3) 63 | dst = cv2.convertScaleAbs(gray_lap) 64 | #对灰度图 65 | kernel_size = 3; scale = 1;delta = 0;ddepth = cv2.CV_16S 66 | img = cv2.GaussianBlur(img,(3,3),0) 67 | gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 68 | gray_lap = cv2.Laplacian(gray,ddepth, ksize = kernel_size,scale = scale,delta = delta) 69 | dst = cv2.convertScaleAbs(gray_lap) 70 | ``` 71 | - canny边缘检测 72 | 算法流程: 73 | 1、高斯滤波平滑。2、计算梯度(sobel,prewitt,roberts都可以)。 74 | 3、非极大值抑制,只保留最大脊线。 75 | 4、8邻域,弱边缘集成到强边缘。(大于T2为强边缘,T1与T2之间为弱边缘) 76 | 77 | ```python 78 | #使用Canny算子进行边缘检测 79 | edge_output = cv2.Canny(out_img_GRAY, 10, 300) 80 | #用sobel算子进行边缘检测 81 | sobel = cv2.Sobel(out_img_GRAY,-1,1,0,ksize=3) 82 | ``` 83 | 84 | ## Hough变换的线检测 85 | 参数空间变换,将$xy$坐标系变为$ab$坐标系$y=ax+b$,或$\theta \rho$坐标系$(xcos\theta +ysin\theta =\rho)$。 86 | ``` 87 | >>A=[0 0 0 5;0 2 0 0;0 0 0 0;0 0 0 0] 88 | >>S=sparse(A) 89 | S=(2,2) 2 90 | (1,4) 5 91 | >>A=full(S) 92 | ``` 93 | 94 | * MATLAB 95 | 96 | ``` 97 | %绘制Hough变换后空间的曲线 98 | function [h, theta, rho]= hough(f, dtheta, drho) 99 | if nargin<3 100 | drho = 1; 101 | end 102 | if nargin<2 103 | stheta = 1; 104 | end 105 | f = double(f) 106 | [M N] = size(f) 107 | ntheta = ceil(180/dtheta)+1 108 | theta = linspace(-90. 90, ntheta); 109 | D = sqrt((M-1)^2+(N-1)^2) 110 | q = ceil(D/drho) 111 | nrho = 2*q -1 112 | rho = linspace(-q*drho, q*drho, nrho) 113 | 114 | [x, y, val] = find(f) %寻找不为0的索引 115 | x=x-1;y=y-1; 116 | h= zeros(nrho, ntheta) 117 | %可取之处,1000个数一循环,全是向量化。栅格内投票时,直接用sparse 118 | for k = 1:ceil(length(val)/1000) 119 | first = (k-1)*1000+1; 120 | last = min(first+999,length(x)) 121 | x_matrix = repmat(x(first:last), 1, ntheta) %B = repmat(A,m,n);把 A 作为 B 的元素,B 由 m×n 个 A 平铺而成 122 | y_matrix = repmat(y(first:last), 1, ntheta) 123 | val_matrix = repmat(val(first:last), 1, ntheta) 124 | theta_matrix = repmat(theta, size(x_matrix, 1), ntheta)*pi/180 125 | rho_matrix = x_matrix.*cos(theta_matrix)+ y_matrix.*sin(theta_matrix) 126 | slope = (nrho -1)/(rho(end)-rho(1)); 127 | rho_bin_index = round(slope*(rho_matrix - rho(1))+ 1) 128 | theta_bin_index = repmat(1:ntheta, size(x_matrix,1), 1) 129 | %使用sparse把对应元素存入 130 | h=h+ full(sparse(rho_bin_index(:), theta_bin_index(:), val_matrix(:), nrho, ntheta)) 131 | end 132 | ``` 133 | 134 | ### Hough变换做峰值检测 135 | 1、找到包含最大值的Hough变换单元,并记下位置 136 | 2、把第一步找到的最大值点的邻域清零 137 | 3、重复该步骤,一直找到需要的峰值数,或者达到一个指定阈值 138 | 139 | ``` 140 | function[r,c,hnew] = houghpeaks(h, numpeaks, threshhold, nhood) 141 | if nargin <4 142 | nhood = size(h)/50 143 | nhood = max(2*ceil(nhood/2)+1, 1) %保证是奇数 144 | end 145 | if nargin <3 146 | threshold = 0.5* max(h(:)) 147 | end 148 | if nargin<2 149 | numpeaks = 1; 150 | end 151 | done = False 152 | hnew = h; r=[];c=[]; 153 | while ~done 154 | [p,q]= find(hnew == max(hnew(:))) 155 | p=p(1);q=q(1) 156 | if hnew(p, q) >= threshold 157 | r(end +1) = p; c(end +1) = q; 158 | p1=p-(nhood(1)-1)/2;p2=p+(nhood(1)-1)/2; 159 | q1=q-(nhood(2)-1)/2;q2=q+(nhood(2)-1)/2; 160 | [pp, qq]=ndgrid[p1:p2, q1:q2] %ndgrid生成网格 161 | %对于rho方向,超界直接删除 162 | pp=pp(:);qq=qq(:); 163 | badrho = find((pp<1)|(pp>size(h, 1)));%找到在范围内的 164 | pp(badrho) = []; qq(badrho) = []; 165 | %对于theta,[-90,90]形成闭环,即-91°应为89° 166 | theta_too_slow = find(qq<1); 167 | qq(theta_too_slow)=size(h,2)+qq(theta_too_slow) 168 | pp(theta_too_slow)=size(h,1)-pp(theta_too_slow)+1 169 | theta_too_high=find(qq>size(h, 2)) 170 | qq(theta_too_high)=qq(theta_too_high)-size(h,2) 171 | pp(theta_too_high)= size(h,1) -pp(theta_too_high)+1 172 | % 173 | hnew(sub2ind(size(hnew),pp,qq)) =0; 174 | done = length(r) == numpeaks 175 | else 176 | done =true 177 | end 178 | end 179 | ``` 180 | 181 | ### Hough变换做线检测和链接 182 | 确定Hough峰值后,需要确定与这些峰值相关的线段及起始位置。 183 | * 第一步,找到影响峰值的每一个非零值点的位置 184 | 185 | ``` 186 | function[r, c]=houghpixels(f, theta, rho, rbin, cbin) 187 | [x,y,val]=find(f) 188 | x=x-1;y=y-1 189 | theta_c = theta(cbin) *pi/180; 190 | rho_xy = x*cos(theta_c)+ y*sin(theta_c) 191 | nrho = length(rho) 192 | slope = (nrho-1)/(rho(end)-rho(1)) 193 | rho_bin_index = round(slope*(rho_xy -rho(1))+1) 194 | idx = find(rho_bin_index == rbin) 195 | r = x(idx) +1;c=y(idx)+1; 196 | ``` 197 | 198 | * 第二步,将houghpixels找到的位置相关像素组合成线段。步骤如下: 199 | 1、将像素旋转$90°-\theta$,以便他们大概位于同一直线 200 | 2、按旋转的x对像素位置分排序 201 | 3、使用diff函数找到裂口,合并被小空白分离的线段。 202 | 4、返回比最小阈值长的线段 203 | 204 | ``` 205 | function lines = houghlines(f, theta, rho, rr, cc, filllap, minlength) 206 | %theta,rho为HOUGH函数的输出;rr,cc为houghpeaks输出;filllap和minlength为裂口和线段长度阈值 207 | if nargin < 6 208 | fillgap = 20 209 | end 210 | if nargin <7 211 | minlength = 40 212 | end 213 | numlines = 0;lines = struct; 214 | for k = 1: length(rr) 215 | rbin = rr(k); cbin = cc(k); 216 | [r, c] = houghpixels(f, theta, rho, rbin, cbin) 217 | if isempty(r) 218 | continue 219 | end 220 | %坐标旋转矩阵 221 | omega = (90 - theta(cbin)) * pi / 180 222 | T = [cos(omega) sin(omega); -sin(omega) cos(omega)] 223 | xy = [r-1, c-1] * T 224 | x = sort(xy(:, 1)) 225 | %找到比阈值大的间断 226 | diff_x = [diff(x); Inf] 227 | for p = 1: length(idx) - 1 228 | x1= x(idx(p)+1); x2 = x(idx(p + 1)) 229 | linelength = x2 - x1 230 | if linelength > minlength 231 | point1 = [x1, rho(rbin)]; point2 = [x2, rho(rbin)] 232 | Tinv = inv(T) 233 | point1 = point1 * Tinv; point2 = point2 * Tinv; 234 | numlines = numlines + 1 235 | lines(numlines).point1 = point1 +1 236 | lines(numlines).point2 = point2 +1 237 | lines(numlines).length = linelength 238 | lines(numlines).theta = theta(cbin) 239 | lines(numlines).rho = rho(cbin) 240 | end 241 | end 242 | end 243 | ``` 244 | * 使用 245 | ![logo](./images/HOUGH.PNG) 246 | ## 阈值处理 247 | ### 全局阈值 248 | **最大类间方差(Otsu)** 249 | * 类间方差 250 | $${\sigma_B}^2 = \omega_0(\mu_0 - \mu_T)^2 + \omega_1(\mu_1 - \mu_T)^2$$ 251 | 其中,离散概率密度归一函数$p_r(r_q) = \frac{n_q}{n}, q = 0,1,2,\cdot,L-1$ 252 | 253 | 每一类出现的概率$\omega_0 = \sum_{q=0}^{k-1} p_q(r_q)$,$\omega_1 = \sum_{q=k}^{L-1} p_q(r_q)$ 254 | 255 | 平均灰度级$\mu_0 = \sum_{q=0}^{k-1} qp_q(r_q)/\omega_0$,$\mu_1 = \sum_{q=k}^{L-1} qp_q(r_q)/\omega_1$ 256 | 257 | 灰度级从1到k的累积出现概率和平均灰度级(一阶累积矩)$\mu_T = \sum_{q=0}^{L} qp_q(r_q)$ 258 | * 类内方差 259 | ${\sigma_0}^2 = \sum_{q=0}^{k}p_q(r_q)(\mu_0 - \mu_0)^2 / \omega_0$,${\sigma_1}^2 = \sum_{q=k}^{L-1}p_q(r_q)(\mu_1 - \mu_1)^2 / \omega_1$ 260 | ### 局部阈值 261 | 先调整亮度分布再全局阈值,效果相同 262 | 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /CH10/images/HOUGH.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH10/images/HOUGH.PNG -------------------------------------------------------------------------------- /CH10/images/edge.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH10/images/edge.PNG -------------------------------------------------------------------------------- /CH10/images/line.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH10/images/line.PNG -------------------------------------------------------------------------------- /CH10/images/suanzi.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH10/images/suanzi.PNG -------------------------------------------------------------------------------- /CH11/chapter11.md: -------------------------------------------------------------------------------- 1 | # 表示与描述 2 | 对形状感兴趣时,可以选用外部表示(边界—长度、凹凸情况);关注区域属性时,可选用内部表示(组成的像素—颜色、纹理)。 3 | 描述子应尽可能对区域大小、平移与旋转的变换不敏感。 4 | ## 表示 5 | ### 链码 6 | Freeman链码: 7 | ![logo](./images/lianma.PNG) 8 | 归一化差分链码具有唯一性、平移不变性、旋转不变性 9 | ![logo](./images/diff.PNG) 10 | * MATLAB 11 | 12 | ``` 13 | b = boundaries(f, conn, dir) %产生边界,最后一个点与第一个点相同 14 | %找到最长边界 15 | d = cellfun('length', B) 16 | [max_d, k]= max(d) 17 | v= B{k(1)} 18 | %可能序列很长,这时需要二次采样(网格分离) 19 | [s su] = bsubsamp(b, 50) 20 | %Freeman编码 21 | c = fchcode(b, conn, dir) %conn = 4或8; dir= 'same'或'reverse' 22 | %b为np*2个已排序边界点集 23 | %输出c为一结构体 24 | %%c.fcc = Freeman链码(1xnp) 25 | %%c.diff = c.fcc的一阶差分 26 | %%c.mm = 最小幅度的整数(1xnp) %归一化链码 27 | %%c.diffmm = c.mm的一阶差分 %逆时针差分 28 | %%c.x0y0 = 代码开始处坐标(1x2) 29 | ``` 30 | 相关函数为: 31 | ``` 32 | function B = boundaries(BW, conn, dir) 33 | %B是一个{P,1}的元胞数组,每个元胞数组为(Q,2)的矩阵;BW为二值图;conn为4或8;dir为'cw'或'ccw' 34 | if nargin < 3 35 | dir = 'cw' 36 | end 37 | if nargin < 2 38 | conn = 8 39 | end 40 | L = bwlabel(BW, conn) %返回相同大小矩阵的连通域标签 41 | if numOb > 0 42 | B = {zeros(0,2)} 43 | B = repmat(B, numOb, 1) 44 | else 45 | B = {} 46 | end 47 | Lp = padarray(L, [1, 1], 0, 'both') %图像边缘补0,防止越界 48 | M = size(Lp, 1) 49 | if conn == 8 50 | %顺序为N NE E SE S SW W NW 51 | offsets = [-1, M-1, M, M+1, 1, -M+1, -M, -M-1] 52 | else 53 | %顺序为N E S W 54 | offsets = [-1, M, 1, -M] 55 | end 56 | if conn == 8 57 | next_search_direction_lut = [8 8 2 2 4 4 6 6 ] 58 | else 59 | next_search_direction_lut = [4 1 2 3] 60 | end 61 | if conn == 8 62 | next_direction_lut = [2 3 4 5 6 7 8 1] 63 | else 64 | next_direction_lut = [2 3 4 1] 65 | end 66 | START = -1 67 | BOUNDARY = -2 68 | scratch = zeros(100,1) 69 | %找到边界起始点 70 | [rr cc] = find((Lp(2:end-1, :))&(Lp(1:end-2, :) == 0)) 71 | rr = rr+1 72 | 73 | ``` 74 | 75 | ### 最小周长多边形的多边形近似(MPP) 76 | * 步骤: 77 | 1、获得细胞联合体 78 | 2、获取细胞联合体内部区域 79 | 3、以4连接顺时针左边序列的形式获得边界 80 | 4、获得边界的Freeman链码 81 | 5、从链码中获得凸顶点和凹顶点 82 | 6、使用凸顶点构造初始多边形,并删除位于多边形之外的凹顶点(角度大于180°) 83 | 7、用剩下的凸顶点重新构造多边形 84 | 8、继续删除凹顶点 85 | 9、重复7、8,直到没有凹顶点 86 | 87 | ### 标记 88 | 中心至边界的延伸向量只能和边界相交一次,并产生一个角度不断增加的单值函数 89 | ![logo](./images/biaoji.PNG) 90 | ### 边界片段 91 | 任意几何S的凸壳H是包含S的最小凸集。集合的差H-S成为S的**凸缺D**。 92 | 区域边界通过沿S轮廓线标记进入与离开凸缺的点。 93 | 这种处理方法要先减少非重要凹面,进行图像平滑处理 94 | ![logo](./images/bianjiepianduan.PNG) 95 | 96 | ### 骨骼(表示平面区域结构形状) 97 | 中间轴变换(MAT):一个边框为b的区域R,对R中的每个点p,寻找b中的最近邻点。若p比这样的临近点大,则称p属于R的中间轴线。 -------------------------------------------------------------------------------- /CH11/images/bianjiepianduan.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH11/images/bianjiepianduan.PNG -------------------------------------------------------------------------------- /CH11/images/biaoji.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH11/images/biaoji.PNG -------------------------------------------------------------------------------- /CH11/images/diff.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH11/images/diff.PNG -------------------------------------------------------------------------------- /CH11/images/lianma.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/CH11/images/lianma.PNG -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # digital_image_process 2 | 3 | 数字图像处理学习笔记, 根据以下学习指南进行: 4 | 5 | 1. 学习用书: 数字图像处理 MATLAB 版 冈萨雷斯著 6 | 7 | > 推荐两本书,一本偏理论, 一本偏代码实战(Matlab), 打包下载地址: 链接:https://pan.baidu.com/s/1Ir3vW_GwTOXbX-QIHkLkxA 8 | > 提取码:nd2a 9 | > 10 | > 11 | > 偏理论: \<数字图像处理\_第三版\_冈萨雷斯\> 12 | > 13 | > 偏实战: \<数字图像处理(MATLAB版)(中译版)[冈萨雷斯]\> 14 | > 15 | > 包含书里的图片素材 16 | 17 | 2. 学习内容: 第 1 章、 第 2 章、 第 3 章、 第 6 章、 第 9 章的 9.1\~9.3 小节、 18 | 第 10 章的 10.1\~10.3 小节、 第 11 章的 11.1~11.2 小节 19 | 20 | 3. 学习要求:为了增强理解,需要根据自己对方法的理解编写相应的 matlab程 序, 21 | 书中的示例程序可以作为参考。 22 | 23 | 4. 图像处理高阶算法 24 | 学 习 内 容 : SIFT[1], LBP[2], BoW[3], affine transformation[4], similarity 25 | transformation[5] 26 | 27 | [1] material: https://blog.csdn.net/zddmail/article/details/7521424 28 | 29 | code: https://github.com/sun11/sw-sift (matlab 版) 30 | 31 | https://github.com/paulaner/SIFT (python 版) 32 | 33 | [2] material: https://blog.csdn.net/heli200482128/article/details/79204008 34 | 35 | code: https://github.com/michael92ht/LBP ( python 版) 36 | 37 | https://github.com/bikz05/texture-matching ( python 版) 38 | 39 | [3] material: https://blog.csdn.net/tiandijun/article/details/51143765 40 | 41 | code: https://github.com/qijiezhao/SIFT_BOW_Usage ( python 版) 42 | 43 | https://github.com/lucifer726/bag-of-words- ( python 版) 44 | 45 | [4] material: https://www.cnblogs.com/ghj1976/p/5199086.html 46 | 47 | [5] material: https://blog.csdn.net/u014096352/article/details/53526747 48 | 49 | ## 说明 50 | 51 | 由于MATLAB基本操作之前学过,主要对遗忘的内容进行笔记; 52 | 除了MATLAB代码,加入相关Python3代码。其中使用[opencv-python](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_table_of_contents_imgproc/py_table_of_contents_imgproc.html), 53 | [pillow(PIL)](https://pillow.readthedocs.io/en/latest/handbook/index.html), 54 | [skimage](https://scikit-image.org/docs/dev/user_guide)等工具。 55 | 56 | > 很久之前的笔记, 适合CV初学者进行学习 57 | 58 | ## 内容列表(已完成) 59 | 60 | * CH01_CH02:MATLAB数据类型与基本操作; 61 | * CH03:gamma亮度与对比度拉伸变换,直方图均衡化与匹配,空间滤波 62 | * CH06:索引图像概念,图像提取&分离通道,彩色空间转换,彩色映射变换,彩色图像空间滤波,彩色边缘检测,彩色图像分割 63 | * CH09:膨胀,腐蚀,顶帽,黑帽,击中或击不中变换,查找表 64 | * CH10:点、线检测(canny、Hough),阈值处理 65 | * CH11:链码、最小周长多边形的多边形近似、标记、边界片段、骨骼 66 | * 高阶:SIFT 67 | -------------------------------------------------------------------------------- /higher_order_algorithm/BoW.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/BoW.md -------------------------------------------------------------------------------- /higher_order_algorithm/LBP.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/LBP.md -------------------------------------------------------------------------------- /higher_order_algorithm/SIFT.md: -------------------------------------------------------------------------------- 1 | # SIFT原理(尺度不变特征变换匹配算法:Scale-invariant feature transform) 2 | ## SIFT算法分解为如下四步: 3 | 1. 尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。 4 | 2. 关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。 5 | 3. 方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而提供对于这些变换的不变性。 6 | 4. 关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。 7 | ## 高斯模糊 8 | 通常,图像处理程序只需要计算$(6\sigma + 1)*(6\sigma + 1)$的矩阵就可以保证相关像素影响。根据$\sigma$的值,计算出高斯模板矩阵的大小。同时,为了确保**模板矩阵中的元素在[0,1]之间**,需将模板矩阵归一化。 9 | $$G(x,y,\sigma) = \frac{1}{2\pi \sigma^2} e^{-\frac{(x-m/2)^2+(y-n/2)^2}{2\sigma^2}} $$ 10 | ### 分离高斯模糊 11 | 造成边缘图像缺失,$\sigma$越大,图像边缘缺失像素越多。 12 | 二维矩阵变换得到的效果也可以通过在水平方向进行一维高斯矩阵变换加上竖直方向的一维高斯矩阵变换得到。 13 | ** 优点 ** 14 | * 加速计算。因为这样只需要$O(n*M*N)+O(m*M*N)$次计算,而二维不可分的矩阵则需要次计算O(m*n*M*N),其中,m,n为高斯矩阵的维数,M,N为二维图像的维数。 15 | * 两次一维的高斯卷积将消除二维高斯矩阵所产生的边缘。(关于消除边缘的论述如下图2.4所示, 对用模板矩阵超出边界的部分——虚线框,将不做卷积计算。如图2.4中x方向的第一个模板1*5,将退化成1*3的模板,只在图像之内的部分做卷积。 16 | ![logo](./images/gauss.PNG) 17 | ## 尺度空间极值检测 18 | ### 尺度空间理论的基本思想 19 | 在图像信息处理模型中引入一个被视为尺度的参数,通过连续变化尺度参数获得多尺度下的尺度空间表示序列,对这些序列进行尺度空间主轮廓的提取,并以该主轮廓作为一种特征向量,实现边缘、角点检测和不同分辨率上的特征提取等。 20 | 21 | **尺度空间满足视觉不变性** 22 | * 当我们用眼睛观察物体时,一方面当物体所处背景的光照条件变化时,视网膜感知图像的亮度水平和对比度是不同的,因此要求尺度空间算子对图像的分析不受图像的灰度水平和对比度变化的影响,即满足**灰度不变性和对比度不变性**。 23 | * 另一方面,相对于某一固定坐标系,当观察者和物体之间的相对位置变化时,视网膜所感知的图像的位置、大小、角度和形状是不同的,因此要求尺度空间算子对图像的分析和图像的位置、大小、角度以及仿射变换无关,即满足**平移不变性、尺度不变性、欧几里德不变性以及仿射不变性** 24 | ### 尺度空间的表示 25 | 一个图像的尺度空间,$L(x,y,\sigma)$定义为一个变化尺度的高斯函数$G(x,y,\sigma)$与原图像$I(x,y)$的卷积。 26 | $$L(x,y,\sigma) = G(x,y,\sigma) \* I(x,y) $$ 27 | $\sigma$是尺度空间因子,值越小表示图像被平滑的越少,相应的尺度也就越小。大尺度对应于图像的概貌特征,小尺度对应于图像的细节特征。 28 | ### 高斯金字塔的构建 29 | 尺度空间在实现时使用高斯金字塔表示,高斯金字塔的构建分为两部分: 30 | 1. 对图像做不同尺度的高斯模糊; 31 | 2. 对图像做降采样(隔点采样,大小减为一半)。 32 | ![logo](./images/pyramid.PNG) 33 | * 金字塔层数 34 | 每个金字塔共n层。金字塔的层数根据图像的原始大小和塔顶图像的大小共同决定,其计算公式如下: 35 | $$n = \log_2 {min(M,N)} - t t\epsilon [0,\log_2 {min(M,N)})$$ 36 | 其中M,N为原图像的大小,t为塔顶图像的最小维数的对数值。如,对于大小为512*512的图像,金字塔上各层图像的大小如表3.1所示,当塔顶图像为4*4时,n=7,当塔顶图像为2*2时,n=8。 37 | ![logo](./images/pyramid_table.PNG) 38 | * 金字塔每层的组(Octave) 39 | 图像金字塔每层的一张图像使用不同参数做高斯模糊,使得金字塔的每层含有多张高斯模糊图像,将金字塔每层多张图像合称为一组(Octave). 40 | 另外,降采样时,高斯金字塔上一组图像的初始图像(底层图像)是由前一组图像的**倒数第三张图像**隔点采样得到的。 41 | ``` 42 | 第0组(即第-1组): 0 1 2 3 4 5 43 | 第1组: 6 7 8 9 10 11 44 | 第2组: ? 45 | 则第2组第一张图片根据第一组中索引为9的图片降采样得到,其它类似 46 | ``` 47 | ### 高斯差DOG分金字塔 48 | * 高斯拉普拉斯函数\sigma^2 \nabla^2 G 49 | 尺度归一化的高斯拉普拉斯函数的极大值和极小值同其它的特征提取函数(梯度,Hessian或Harris角特征比较),能够产生最稳定的图像特征。 50 | * 高斯差分函数 51 | 与尺度归一化的高斯拉普拉斯函数非常近似,利用差分近似代替微分,则有: 52 | $$\sigma^2 \nabla^2 G = \frac{\partial G}{\partial \sigma} \approx \frac{G(x,y,k\sigma)-G(x,y,\sigma)}{k\sigma-\sigma}$$ 53 | $$G(x,y,k\sigma)-G(x,y,\sigma) \approx (k-1)\sigma^2 \nabla^2 G $$ 54 | 其中k-1是个常数,并不影响极值点位置的求取。 55 | ![logo](./images/DOG.PNG) 56 | $$ D(x,y,\sigma) = (G(x,y,k\sigma)-G(x,y,\sigma))*I(x,y) = L(x,y,k\sigma)-L(x,y,\sigma)$$ 57 | 在实际计算时,使用高斯金字塔每组中相邻上下两层图像相减,得到高斯差分图像,如图3.3所示 58 | ![logo](./images/dog_p.PNG) 59 | ### 空间极值点检测(关键点的初步探查) 60 | 关键点是由DOG空间的局部极值点组成的。关键点的初步探查是通过同一组内各DoG相邻两层图像之间比较完成的。 61 | 每一个像素点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。 62 | ![logo](./images/updown.PNG) 63 | * 同尺度比较 64 | 中间的检测点和它同尺度的8个相邻点,保证在二维图像空间有极值点 65 | * 上下相邻尺度比较(组内,尺度代表$\sigma$) 66 | 上下相邻尺度对应的9×2个点共26个点比较,以确保在尺度空间检测到极值点。 67 | 为了在每组中检测S个尺度的极值点,则DOG金字塔每组需S+2层图像,而DOG金字塔由高斯金字塔相邻两层相减得到,则高斯金字塔每组需S+3层图像,实际计算时S在3到5之间。 68 | ### 构建尺度空间需确定的参数 69 | * $\sigma$尺度空间坐标计算 70 | $$\sigma(o,s)=\sigma_0 2^{o+\frac{s}{S}} o\epsilon [0,\cdot,O-1] s\epsilon[0,\cdot,S+2]$$ 71 | 其中$\sigma_0$是基准层尺度,o为组octave的索引,s为组内层的索引。O为组(octave)数,S为组内层数。 72 | * 第-1组 73 | 在最开始建立高斯金字塔时,要预先模糊输入图像来作为第0个组的第0层的图像,这时相当于丢弃了最高的空域的采样率。因此通常的做法是先将图像的尺度扩大一倍来生成第-1组。 74 | 75 | ![logo](./images/pyramidf.PNG) 76 | ## 关键点定位 77 | 以上方法检测到的极值点是离散空间的极值点,以下通过拟合三维二次函数来精确确定关键点的位置和尺度, 78 | 同时去除低对比度的关键点和不稳定的边缘响应点(因为DoG算子会产生较强的边缘响应),以增强匹配稳定性、提高抗噪声能力。 79 | ### 关键点的精确定位 80 | 离散空间的极值点并不是真正的极值点,利用已知的离散空间点插值得到的连续空间极值点的方法叫做子像素插值(Sub-pixel Interpolation)。 81 | 为了提高关键点的稳定性,需要对尺度空间DoG函数进行曲线拟合。利用DoG函数在尺度空间的Taylor展开式(拟合函数)为: 82 | $$D(X)= D + \frac{\partial D^T}{\partial X} + \frac{1}{2}X^T \frac{\partial^2 D}{\partial X^2}X$$ 83 | 其中,$X=(x,y,\sigma)^T$。求导等于零,获得极值点偏移量: 84 | $$\hat{X} = - \frac{\partial^2 D^{-1}}{\partial X^2} \frac{\partial D}{\partial X}$$ 85 | 对应极值点,方程的值为: 86 | $$D(\hat{X})=D+\frac{1}{2} \frac{\partial D^T}{\partial X} \hat{X}$$ 87 | 当$\hat{X}$在任一维度上的偏移量大于0.5时(即x或y或$\sigma$),意味着插值中心已经偏移到它的邻近点上,所以必须改变当前关键点的位置。同时在新的位置上反复插值直到收敛;也有可能超出所设定的迭代次数或者超出图像边界的范围,此时这样的点应该删除 88 | 另外,$|D(X)|$过小的点易受噪声的干扰而变得不稳定,所以|D(X)|将小于某个经验值(Lowe论文中使用0.03,Rob Hess等人实现时使用0.04/S)的极值点删除。 89 | 同时,在此过程中获取特征点的精确位置(原位置加上拟合的偏移量)以及尺度($\sigma(o,s)和\sigma_oct(s)$) 90 | ### 消除边缘响应 91 | 一个定义不好的高斯差分算子的极值在横跨边缘的地方有较大的主曲率,而在垂直边缘的方向有较小的主曲率。 92 | 93 | DOG算子会产生较强的边缘响应,需要剔除不稳定的边缘响应点。获取特征点处的Hessian矩阵,主曲率通过一个2x2 的Hessian矩阵H求出 94 | $$\left[ 95 | \begin{matrix} 96 | D_xx & D_xy\\ 97 | D_xy & D_yy\\ 98 | \end{matrix} 99 | \right] 100 | $$ 101 | H的特征值$\alpha$和$beta$代表x和y方向的梯度, 102 | $$Tr(H)=D_xx+D_yy = \alpha + \beta$$ 103 | $$Det(H) = D_xx D_yy -(D_xy)^2$$ 104 | 假设是α较大的特征值,而是β较小的特征值,令$\alpha = r\beta$,则 105 | $$\frac{Tr(H)^2}{Det(H)} = \frac{(r\beta + \beta)}{r \beta^2}= \frac{(r+1)^2}{r}$$ 106 | 所以为了剔除边缘响应点,需要让该比值小于一定的阈值,因此,为了检测主曲率是否在某域值r下,只需检测 107 | $$ \frac{Tr(H)^2}{Det(H)} < \frac{(r+1)^2}{r}$$ 108 | 109 | ### 有限差分法求导 110 | 有限差分法以变量离散取值后对应的函数值来近似微分方程中独立变量的连续取值。 111 | 这种方法仍然可以达到任意满意的计算精度。因为方程的连续数值解可以通过减小独立变量离散取值的间格,或者通过离散点上的函数值插值计算来近似得到。 112 | **有限差分法的具体操作分为两个部分** 113 | 1.用差分代替微分方程中的微分,将连续变化的变量离散化,从而得到差分方程组的数学形式 114 | 2.求解差分方程组 115 | 116 | 一个函数在x点上的一阶和二阶微商,可以近似地用它所临近的两点上的函数值的差分来表示。 117 | 118 | 如对一个单变量函数f(x),x为定义在区间[a,b]上的连续变量,以步长将区间[a,b]离散化,我们会得到一系列节点 119 | $$x_1 =, x_2 = x_1 +h,..., x_{n+1}=x_n +1=b $$ 120 | 然后求出f(x)在这些点上的近似值。显然步长h越小,近似解的精度就越好。与$x_i$节点相邻的节点有$x_i -h$和$x_i +h$,所以在$x_i$节点处可构造如下形式的差值: 121 | * $f(x_i +h)-f(x_i)$节点的一阶向前差分 122 | * $f(x_i)-f(x_i -h)$节点的一阶向后差分 123 | * $f(x_i +h)-f(x_i -h)$节点的一阶中心差分 124 | 125 | 本文使用中心差分法利用泰勒展开式求解第四节所使用的导数,现做如下推导。 126 | 函数f(x)在$x_i$处的泰勒展开式为: 127 | ![logo](./images/diff1.png) 128 | ![logo](./images/diff2.png) 129 | ![logo](./images/diff3.PNG) 130 | ### 三阶矩阵求逆公式 131 | 高阶矩阵的求逆算法主要有归一法和消元法两种,现将三阶矩阵求逆公式总结如下: 132 | ![logo](./images/ni.PNG) 133 | ## 关键点方向分配 134 | ![logo](./images/fangxiang.PNG) 135 | ## 关键点特征描述 136 | 使用在关键点尺度空间内4*4的窗口中计算的8个方向的梯度信息,共4*4*8=128维向量表征。 137 | ![logo](./images/digram.PNG) 138 | 139 | # SIFT缺点 140 | SIFT在图像的不变特征提取方面拥有无与伦比的优势,但并不完美,仍然存在: 141 | 142 | 1. 实时性不高。 143 | 144 | 2. 有时特征点较少。 145 | 146 | 3. 对边缘光滑的目标无法准确提取特征点。 147 | 148 | 等缺点,如下图7.1所示,对模糊的图像和边缘平滑的图像,检测出的特征点过少,对圆更是无能为力。近来不断有人改进,其中最著名的有SURF和CSIFT。 149 | ![logo](./images/sift_con.PNG) 150 | 151 | -------------------------------------------------------------------------------- /higher_order_algorithm/affine_transformation.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/affine_transformation.md -------------------------------------------------------------------------------- /higher_order_algorithm/images/DOG.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/DOG.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/diff1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/diff1.png -------------------------------------------------------------------------------- /higher_order_algorithm/images/diff2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/diff2.png -------------------------------------------------------------------------------- /higher_order_algorithm/images/diff3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/diff3.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/digram.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/digram.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/dog_p.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/dog_p.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/fangxiang.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/fangxiang.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/gauss.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/gauss.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/ni.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/ni.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/pyramid.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/pyramid.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/pyramid_table.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/pyramid_table.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/pyramidf.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/pyramidf.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/sift_con.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/sift_con.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/images/updown.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/images/updown.PNG -------------------------------------------------------------------------------- /higher_order_algorithm/similarity_transformation.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiuFG/digital_image_process/2c2a10c61497eaca3c418572a8cc32adfea0d1be/higher_order_algorithm/similarity_transformation.md --------------------------------------------------------------------------------