图像转数组_图像处理100题习题与代码(1~10)

20c6eb728597191e73308cf868f9dd22.png
题目原地址: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
输出-1

3d07654574baf3fbdba49aa768781393.png
输出-1

2.灰度化(Grayscale)

通过公式

计算得出单通道Y

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
输入-2

5eba938d8cfc77230e18a594377ccbd6.png
输出-2

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
输入-3

86d387273754ac542705a04cf160f000.png
输出-3

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
输入-4

086c7f2e30bbdf686148e223dea81170.png
输出-4

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
输入-5

b0612fae447086ca5bec748d2405e6eb.png
输出-5

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
输入-6

64d3320e1ca0fe0efcf16807c6e80982.png
输出-6

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
输入-7

16404106085258cd7e08e4af1e720dbb.png
输出-7

8.最大池化(Max Pooling)

网格内的值不取平均值,而是取网格内的最大值进行池化操作。

一定范围内的像素点全部转为该范围的最大值
imshow = plt.imshow(img)
plt.show()

img8 = img.copy()
img8 = pooling(img8,8,"max")
imshow = plt.imshow(img8)

bcc04349d2afd3c497a12a7d9cfe697d.png
输入-8

a37229b688d70fe5f6996c2d33cbcbbf.png
输出-8

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
输入-9

d37993b9165e3c26d1647248167f2dec.png
输出-10

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
输入-10

1528bce6aa47a2d8be63211e15eea039.png
输出-10

原创首发,欢迎来我的博客留言讨论

我的博客主页:

CSDN-个人空间​me.csdn.net
d9e89b4e84a8a230cfa0a02e103a9235.png

我的知乎专栏:

LeonG与机器学习​zhuanlan.zhihu.com
0f721ad170f113bc6e239398e26cfb84.png

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值