自此记录我艰难的数字图像处理生活

实验一:图像插值

实验原理

理解图像插值的原理及实验
掌握最近邻、双线性、双三次等插值方法的不同

实验内容与结果分析

1、最近邻插值法

for des_x in range(0, desHeight):
    for des_y in range(0, desWidth):
        # 判断新像素点在原图中的像素点坐标
        src_x = int(des_x * (height / desHeight))
        src_y = int(des_y * (width / desWidth))
        desImage[des_x, des_y] = img[src_x, src_y]  # 填充
print(desImage.shape)
des_img = Image.fromarray(desImage)
des_img.save('D:\Program Files (x86)\Pycharm\images_process\images\output\\test_1.jpg')

2、双线性插值法

def Interpolation_Bilinear(filepath, desHeight, desWidth):
    # 双线性插值法
    img = Image.open(filepath)  # 读取图片
    img = np.array(img, np.uint8)  # 转化为numpy数组
    desImageNumpy = np.zeros(img.shape, np.uint8)  # 生成一个大小相同的全0的numpy数组
    height, width, mode = img.shape[0], img.shape[1], img.shape[2]  # 高、宽、channel数

    # 找出目标位置在源图中的位置
    scale_x = float(width)/desWidth  # x轴缩放比例
    scale_y = float(height)/desHeight  # y轴缩放比例
    des_image = np.zeros((desHeight, desWidth, mode), np.uint8)
    for n in range(mode):
        for des_y in range(desHeight):
            for des_x in range(desWidth):
                # 确定四个近邻点坐标
                src_x = (des_x + 0.5) * scale_x - 0.5  
                src_y = (des_y + 0.5) * scale_y - 0.5
			src_x_1 = int(np.floor(src_x))  #
            src_y_1 = int(np.floor(src_y))
            src_x_2 = min(src_x_1+1, width-1)  # 防止坐标点寻找溢出
            src_y_2 = min(src_y_1+1, height-1)
            # 两次x轴线性插值
            value_1 = (src_x_2 - src_x)*img[src_y_1, src_x_1, n]+(src_x - src_x_1)*img[src_y_1, src_x_2, n]
            value_2 = (src_x_2 - src_x)*img[src_y_2, src_x_1, n]+(src_x - src_x_1)*img[src_y_2, src_x_2, n]
            # y轴线性插值
            des_image[des_y, des_x, n] = (src_y_2 - src_y)*value_1 + (src_y - src_y_1)*value_2
print(des_image.shape)
des_img = Image.fromarray(des_image)
des_img.save('D:\Program Files (x86)\Pycharm\images_process\images\output\\test_2.jpg')

3、双三次插值法

def BiCubic_interpolation(img,dstH,dstW):
    scrH,scrW,_=img.shape
    #img=np.pad(img,((1,3),(1,3),(0,0)),'constant')
    retimg=np.zeros((dstH,dstW,3),dtype=np.uint8)
    for i in range(dstH):
        for j in range(dstW):
            scrx=i*(scrH/dstH)
            scry=j*(scrW/dstW)
            x=math.floor(scrx)
            y=math.floor(scry)
            u=scrx-x
            v=scry-y
            tmp=0
            for ii in range(-1,2):
                for jj in range(-1,2):
                    if x+ii<0 or y+jj<0 or x+ii>=scrH or y+jj>=scrW:
                        continue
                    tmp+=img[x+ii,y+jj]*BiBubic(ii-u)*BiBubic(jj-v)
            retimg[i,j]=np.clip(tmp,0,255)
    return retimg

心得体会

1、找的双三次算法无法运行?

首先,经过对异常的翻译,是图像路径那里D:\Program Files (x86)\Pycharm\images_process\images\2.jpg 最后的2.jpg前面添加为\,而不是只有一个,只有一个的话,计算机会有OSError: [Errno 22] Invalid argument: ‘D:\Program Files (x86)\Pycharm\images_process\images\x02.jpg’ 报错。

//和\的区别
在不同系统的情况下 windows下是’’, linux和unix下是’/’ 但在win中没有本质区别。
但是由于 ‘’ 也是转义字符的起始字符, 所以, 路径中的 ‘’ 通常需要使用 '\'如果是 ‘/’ 就不需要使用转义了
如C中文件操作,c:\hello\word.txt c:/hello/word.txt一样
c++中char *str = “…\testdemo.cpp”; 和char *str = “…/testdemo.cpp”;一样

之后,将\改为\之后(或者将//都改为\)程序可以运行,但是好像程序中有了死循环,无法自己结束,一直运行,图片也无法显示,经过一段处理后,我了解到在输入图像的地方可以使用从cv2.imread()或
Image.open(),

cv2.imread()读取的是图像的真实数据。Image.open()函数只是保持了图像被读取的状态,但是图像的真实数据并未被读取,因此如果对需要操作图像每个元素,如输出某个像素的RGB值等,需要执行对象的load()方法读取数据。具体如下:
img = Image.open(“lena.jpg”)
img = img.load()
print(img[0,0])
#result:(255, 201, 166)

Image.open()得到的是img对象,不是普通的数组
Cv2.imread得到的img数据类型是arr.array()类型

而我们本次实验的是需要数据,所以,我将Image.open()改为从cv2.imread(),但是问题并未解决仍然是陷入在死循环中。。。
之后,我判断是函数体内有问题,scrH,scrW,=img.shape,这个“”让我很疑惑,之后经过查阅,得知
Img.shape属性是读入图片后的一个元组dutuple返回图片的(高,宽,位深(应为通道数))
而这个“”就代表(是自己看到被这个符号给弄懵了,其实就和普通的变量没区别,后面没有调用而已),如果不加这个,就会有ValueError: too many values to unpack (expected 2)的报错,就是因为,img.Shape的返回值有三个,而你只定义了两个变量。

(一个插曲:我在调试过程中,输出时因为误在printf()前敲了一个空格,就报错IndentationError: unexpected indent,可见缩进在python中是十分严谨,重要的)
同时,我又对shape返回值中的“位深”产生了疑惑,啥是位深?
这个位深,通过查询,网上有人说好像就是通道数的意思,(调试中print的值是3);但也有字面意思就是位深度,但在图片的属性中所查看的详细信息中位深度是24位(可表示颜色为2^24)并不是3,所以,网上所告诉我的这个shape的返回值中的“位深”并不是真正的位深的意思,就是通道的意思,其中2通道位深为8,三通道为24
(这里在网上越查发现的东西越多,好多都看不懂了,先开个坑以后再慢慢来。。。)

之后,我又往下看代码,又发现了新的问题:对python不了解,不知道for循环的格式,以及往下的Range()函数等
经查询,for循环可用于:遍历、修改列表、删除列表、统计列表某一元素个数、阶乘、遍历字符串、遍历集合对象、遍历文件、遍历字典
其中range()函数
python range() 函数可创建一个整数列表,一般用在 for 循环中。
函数语法
range(start, stop[, step])
参数说明:
start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5);
stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)
图中所见的是range(dstH)即至dstH结束

2、在解决问题1时,发现自己对三种数值插入方式十分不熟悉?

Why?为什么要学图像插值?
因为在将图像放大的过程中要将源图放大,而原图放大就类似于将3×3的矩阵变为4×4的,而这个4×4的目标图的各个像素都是未知的,因此就需要一种填充方法来获得放大后的目标图的像素。而这种填充方法就是图像插值。

How?三种算法的原理
① 最近邻插值
将原图像最近邻的灰度赋给每个新位置
作用:方法简单,会产生严重的失真,如严重的直边失真
② 双线性插值
将原图四个最近邻的灰度来计算给定位置的灰度
③ 双三次插值
将原图16个最近邻的点来计算给定位置
(但是,如何用代码来表示这三个算法呢?通过查询,实在看不懂,还要继续学习。。。。)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值