![20c6eb728597191e73308cf868f9dd22.png](https://i-blog.csdnimg.cn/blog_migrate/eb4f837fbecc9d350b7071f5dd613901.jpeg)
题目原地址:https://github.com/gzr2017/ImageProcessing100Wen
我的github地址:https://github.com/LeonG7/image_100question
前言:
这是图像处理100题的题目记录以及我自己写的参考代码,感谢@gzr2017提供中文翻译。
所有代码由jupyter book软件导出,如需可执行源代码,请在我的github下载。
如有任何问题或错误,欢迎在评论区讨论和指正
图像处理1~10题
读取图片:
import cv2
import matplotlib
from matplotlib import pyplot as plt
import numpy as np
%matplotlib inline
img = cv2.imread("imori.jpg")
img_noise = cv2.imread("imori_noise.jpg")
#使用matplotlib输出图片,所以要将BGR格式预先转为RBG格式
img = img[:,:,[2,1,0]]
img_noise = img_noise[:,:,[2,1,0]]
1.通道交换
将红色通道和蓝色通道交换,交换通道维的第一列和第三列即可。
imshow = plt.imshow(img)
plt.show()
img1 = img.copy()
img1 = img[:,:,[2,1,0]]
imshow = plt.imshow(img1)
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![3d07654574baf3fbdba49aa768781393.png](https://i-blog.csdnimg.cn/blog_migrate/ae5d8ccabd64a425ef10197dd4a4313e.jpeg)
2.灰度化(Grayscale)
通过公式
matplotlib中的cmap = gray
#灰度化
def gray(img):
newimg = img[:,:,0]*0.2126 + img[:,:,1]*0.7152 + img[:,:,2]*0.0722
return newimg
imshow = plt.imshow(img)
plt.show()
img2 = gray(img)
imshow = plt.imshow(img2,cmap='gray')
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![5eba938d8cfc77230e18a594377ccbd6.png](https://i-blog.csdnimg.cn/blog_migrate/006771f8e76c6d8fdc38e0cef395210c.jpeg)
3.二值化(Thresholding)
把图像进行二值化吧。
计算出灰度化的值之后,对像素点进行判断:
二值化是将图像使用黑和白两种颜色表示的方法。
#二值化
def thre(img,t=128):
img[img<t] = 0
img[img>=t] = 255
return img
imshow = plt.imshow(img)
plt.show()
img3 = gray(img)
img3 =thre(img3)
imshow = plt.imshow(img3,cmap='gray')
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![86d387273754ac542705a04cf160f000.png](https://i-blog.csdnimg.cn/blog_migrate/b65faf9799421a4936cfbe93906ef057.jpeg)
4.大津二值化算法(Otus's Method)
即:
- 类内方差:
- 类间方差:
- 图像所有像素的方差:
根据以上的式子,我们用以下的式子计算分离度
也就是说:
换言之,如果使
求出一个阈值,使得类间方差最大化
#计算最大类间方差
def oturs(img):
t = 0
sd = 0
for i in range(255):
newsd = sfunc(img,i)
if newsd > sd:
sd = newsd
t = i
return t
#计算类间方差
def sfunc(img,t):
w = img > t
w1 = w.sum()/w.size
w0 = 1-w1
if w1==0 or w0==0:
return 0
m1 = np.mean(img[w])
m0 = np.mean(img[~w])
return w0*w1*(m0-m1)*(m0-m1)
imshow = plt.imshow(img)
plt.show()
img4 = img.copy()
img4 = gray(img4)
t = oturs(img4)
img4 = thre(img4,t)
imshow = plt.imshow(img4,cmap='gray')
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![086c7f2e30bbdf686148e223dea81170.png](https://i-blog.csdnimg.cn/blog_migrate/3a65c2f5fa039a57fc0faafcc4b2e74b.jpeg)
5.HSV变换
(知乎上公式不好写,具体参考我的csdn博客,也可以从我的github中下载题目)
将RGB图片转为HSV,即色相、饱和度、明度
然后将色相反转,再转回RGB输出
def rgb2hsv(img):
#标准化
img = img/255
#将img拉成 [128*128,3] 方便计算
old_shape = img.shape
img = img.reshape(-1,3)
R,G,B = img[:,0],img[:,1],img[:,2]
max = np.max(img,axis=1)
min = np.min(img,axis=1)
hsv = np.zeros_like(img)
#计算色相
h_b = min == B
h_r = min == R
h_g = min == G
hsv[h_b,0] = 60*(G[h_b]-R[h_b])/(max[h_b]-min[h_b])+60
hsv[h_r,0] = 60*(B[h_r]-G[h_r])/(max[h_r]-min[h_r])+180
hsv[h_g,0] = 60*(R[h_g]-B[h_g])/(max[h_g]-min[h_g])+300
#饱和度
hsv[:,1] = max-min
#明度
hsv[:,2] = max
return hsv.reshape(old_shape)
def hsv2rgb(img):
#色相是环形的,所以要模360°
img[:,:,0] = np.mod(img[:,:,0],360)
old_shape = img.shape
img = img.reshape(-1,3)
c = img[:,1]
h = img[:,0]/60
x = c*(1-np.abs(np.mod(h,2)-1))
v = img[:,2]
#计算rgb
#先建立v-c的基础数组,v-c*(1,1,1)
v_c = (v-c).reshape(-1,1)
rgb = np.repeat(v_c,3,axis=1)
#划分条件,组合起来加到初始数组上
h0 = (h>=0)*(h<1)
zero = np.zeros(h0.sum())
rgb[h0] += np.vstack((c[h0],x[h0],zero)).T
h1 = (h>=1)*(h<2)
zero = np.zeros(h1.sum())
rgb[h1] += np.vstack((x[h1],c[h1],zero)).T
h2 = (h>=2)*(h<3)
zero = np.zeros(h2.sum())
rgb[h2] += np.vstack((zero,c[h2],x[h2])).T
h3 = (h>=3)*(h<4)
zero = np.zeros(h3.sum())
rgb[h3] += np.vstack((zero,x[h3],c[h3])).T
h4 = (h>=4)*(h<5)
zero = np.zeros(h4.sum())
rgb[h4] += np.vstack((x[h4],zero,c[h4])).T
h5 = (h>=5)*(h<6)
zero = np.zeros(h5.sum())
rgb[h5] += np.vstack((c[h5],zero,x[h5])).T
return rgb.reshape(old_shape)
imshow = plt.imshow(img)
plt.show()
img5 = img.copy()
img_hsv = rgb2hsv(img5)
img_hsv[:,:,0]+=180
img5 = hsv2rgb(img_hsv)
imshow = plt.imshow(img5)
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![b0612fae447086ca5bec748d2405e6eb.png](https://i-blog.csdnimg.cn/blog_migrate/85919dee887bb96573937ebc6a70e65e.jpeg)
6.减色处理
将RGB的【0~255】范围离散化至【32 , 96 , 160 , 224】
def dcolor(img):
img[img<64] = 32
img[(img>=64)*(img<128)] = 96
img[(img>=128)*(img<192)] = 160
img[(img>=192)*(img<256)] = 224
return img
imshow = plt.imshow(img)
plt.show()
img6 = img.copy()
img6 = dcolor(img)
imshow = plt.imshow(img6)
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![64d3320e1ca0fe0efcf16807c6e80982.png](https://i-blog.csdnimg.cn/blog_migrate/707bd88314fa49861f59481208576542.jpeg)
7.平均池化(Average Pooling)
将图片按照固定大小网格分割,网格内的像素值取网格内所有像素的平均值。
我们将这种把图片使用均等大小网格分割,并求网格内代表值的操作称为池化(Pooling)。
池化操作是卷积神经网络(Convolutional Neural Network)中重要的图像处理方式。平均池化按照下式定义:
请把大小为128的图片使用8的网格做平均池化。
一定范围内的像素点全部转为该范围的平均值。
def pooling(img,length,method):
for i in range(int(img.shape[0]/length)):
for j in range(int(img.shape[1]/length)):
area = img[i*length:(i+1)*length,j*length:(j+1)*length]
if(method=="avg"):
area[:,:,0] = area[:,:,0].mean()
area[:,:,1] = area[:,:,1].mean()
area[:,:,2] = area[:,:,2].mean()
if(method=="max"):
area[:,:,0] = area[:,:,0].max()
area[:,:,1] = area[:,:,1].max()
area[:,:,2] = area[:,:,2].max()
return img
imshow = plt.imshow(img)
plt.show()
img7 = img.copy()
img7 = pooling(img7,8,"avg")
imshow = plt.imshow(img7)
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![16404106085258cd7e08e4af1e720dbb.png](https://i-blog.csdnimg.cn/blog_migrate/d7b66a6f9adc7ce6966a99e4ecd266d4.jpeg)
8.最大池化(Max Pooling)
网格内的值不取平均值,而是取网格内的最大值进行池化操作。
一定范围内的像素点全部转为该范围的最大值
imshow = plt.imshow(img)
plt.show()
img8 = img.copy()
img8 = pooling(img8,8,"max")
imshow = plt.imshow(img8)
![bcc04349d2afd3c497a12a7d9cfe697d.png](https://i-blog.csdnimg.cn/blog_migrate/952a8ebfd0855def67edbd711f029808.jpeg)
![a37229b688d70fe5f6996c2d33cbcbbf.png](https://i-blog.csdnimg.cn/blog_migrate/22c8ee176fe9c3ba7f6b753acef2a306.jpeg)
9.高斯滤波
高斯滤波器是一种可以使图像平滑的滤波器,用于去除噪声。可用于去除噪声的滤波器还有中值滤波器(参见问题十),平滑滤波器(参见问题十一)、LoG滤波器(参见问题十九)。
高斯滤波器将中心像素周围的像素按照高斯分布加权平均进行平滑化。这样的(二维)权值通常被称为卷积核(kernel)或者滤波器(filter)。
1.先设定一个高斯核,高斯核的值由二维高斯函数计算得出
2.高斯核进行标准化,也就是和为1
3.对于每一个像素点,以它为中心取和高斯核相同大小的方块
4.将高斯核和方块相乘后累加,得出的值就是这个像素点的高斯滤波值
def padding(img,s=1):
#先加行
rows = np.zeros((s,img.shape[1],img.shape[2]),dtype="uint8")
#再加列,这时候列长已经扩充 2*s
columns = np.zeros((img.shape[0]+(2*s),s,img.shape[2]),dtype="uint8")
#拼接
img = np.vstack((rows,img,rows))
img = np.hstack((columns,img,columns))
return img
def getarea(img,padding,method):
#建立一个新的数组,该数组用于保存计算的高斯滤波值,所以要去掉padding
result = np.zeros([img.shape[0]-2*padding,
img.shape[1]-2*padding,
img.shape[2]],dtype="uint8")
for i in range(int(img.shape[0]-2)):
for j in range(int(img.shape[1]-2)):
area = img[i:i+3,j:j+3]
if(method=="gaussian"):
#将像素值赋值到中心点
kernel = np.array([1,2,1,2,4,2,1,2,1])*(1/16)
result[i,j,:] = gaussFilter(area,kernel)
if(method=="median"):
result[i,j,:] = medianFilter(area)
return result
def gaussFilter(area,kernel):
#拉成一条,用矩阵的乘法完成滤波计算,参考卷积核计算方法
area = area.reshape(-1,3)
newk = np.dot(kernel,area)
newk = newk.astype(np.uint8)
return newk
imshow = plt.imshow(img_noise)
plt.show()
img9 = img_noise.copy()
img9 = padding(img9,1)
img9 = getarea(img9,1,"gaussian")
imshow = plt.imshow(img9)
![17c6335bc859bce33a3bd199b702d110.png](https://i-blog.csdnimg.cn/blog_migrate/dd0e629752e8c84566f6b36ebc06a958.jpeg)
![d37993b9165e3c26d1647248167f2dec.png](https://i-blog.csdnimg.cn/blog_migrate/ff87508b9e9a76c38922b2e0f415682e.jpeg)
10.中值滤波
中值滤波器是一种可以使图像平滑的滤波器。这种滤波器用滤波器范围内像素点的中值进行滤波,请在这里也采用Zero Padding。
在滤波器中,取范围内的中值数填入中心点
def medianFilter(area):
#拉成一条,并且转置为横向
area = area.reshape(-1,3).T
#进行排序后取出中间值
newk = np.sort(area,axis=1)[:,4]
return newk
imshow = plt.imshow(img_noise)
plt.show()
img10 = img_noise.copy()
img10 = padding(img10,1)
img10 = getarea(img10,1,"median")
imshow = plt.imshow(img10)
![17c6335bc859bce33a3bd199b702d110.png](https://i-blog.csdnimg.cn/blog_migrate/dd0e629752e8c84566f6b36ebc06a958.jpeg)
![1528bce6aa47a2d8be63211e15eea039.png](https://i-blog.csdnimg.cn/blog_migrate/9ae1a8d986816109c8d5c34bff96c58c.jpeg)
原创首发,欢迎来我的博客留言讨论
我的博客主页:
CSDN-个人空间me.csdn.net![d9e89b4e84a8a230cfa0a02e103a9235.png](https://i-blog.csdnimg.cn/blog_migrate/7e343631d65087cbf20380f2548a43bb.png)
我的知乎专栏:
LeonG与机器学习zhuanlan.zhihu.com![0f721ad170f113bc6e239398e26cfb84.png](https://i-blog.csdnimg.cn/blog_migrate/8f80038e33549982e1b4d20ba053ea57.jpeg)
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。