python图像处理实验:图像处理基本操作

实验一:图像处理基本操作

一、实验目的

1、熟悉并掌握MATLAB工具的使用;

2、实现图像的读取、显示、存储、平移、镜像、放大、缩小及旋转操作;

3、掌握常用的插值方法,并了解其优缺点。

二、实验环境

IDE:pycharm

Python

三、实验内容(题目、相关知识(函数,原理…)、代码、实验结果)

1、读入一幅RGB图像(自选),变换为灰度图像和二值图像,并在同一个窗口内分别显示RGB图像和灰度图像,注上文字标题,并将结果以文件形式存到磁盘上。

灰度变换属于空域变换增强技术。

目的:

一般成像系统形成图像的亮度有限,对比度不足,使图像的视觉效果差,灰度变换即可有效地改善视觉效果。

概念:

灰度变换是一种点操作,根据原始图像中每个像素的灰度值,按照某种映射规则将其转化为另一灰度值。灰度变换可有效改善图像的视觉效果,变换原理可表示为如式所示:

t = E(k)

式中:k为原始图像的灰度值f(x,y),t为变换图像的灰度值g(x,y),E()为灰度增强函数。

原理:

灰度变换原理可由图来说明,其中,图(a)为原始图像,具有两种灰度级,分别用B和W来表示;图(b)为灰度增强函数,根据函数的映射规则,原始图像的灰度值B映射为灰度值W,原始图像的灰度值W映射为灰度值B;图(c)为变换后的图像。
在这里插入图片描述

灰度变换的关键在于根据增强要求设计灰度映射规则,即设计灰度增强函数。典型灰度变换函数包括:比例线性变换、分段线性变换、非线性变换

图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。二值图像每个像素只有两种取值:要么纯黑,要么纯白。由于二值图像数据足够简单,许多视觉算法都依赖二值图像。通过二值图像,能更好地分析物体的形状和轮廓。二值图像也常常用作原始图像的掩模(又称遮罩、蒙版,Mask):它就像一张部分镂空的纸,把我们不感兴趣的区域遮掉。进行二值化有多种方式,其中最常用的就是采用阈值法(Thresholding)进行二值化。

转换为灰度图像使用函数cvColor,这里转化为二值图像直接设置阈值判断灰度值大小,如果灰度值大于阈值直接赋值为255,反之赋值为0

实验代码:
在这里插入图片描述

实验结果:
在这里插入图片描述

2、对图像(自选)执行平移、镜像(水平镜像、垂直镜像)放大、缩小及旋转操作,其中放大、旋转操作分别采用最近邻插值及双线性插值方法实现,要求根据算法自己编写代码实现,并分析两种插值方法的优缺点。

(1)平移

图像平移首先定义平移矩阵M,再调用warpAffine()函数实现平移,python函数如下:

M = np.float32([[1, 0, x], [0, 1, y]])

M表示平移矩阵,其中x表示水平平移量,y表示垂直平移量

shifted = cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])

src表示原始图像

M表示平移矩阵

dsize表示变换后的输出图像的尺寸大小

dst为输出图像,其大小为dsize,类型与src相同

flag表示插值方法的组合和可选值

borderValue表示像素外推法,当borderMode = BORDER_TRANSPARENT时,表示目标图像中的像素不会修改源图像中的“异常值”。

borderValue用于边界不变的情况,默认情况下为0
在这里插入图片描述

平移后图像

(2)旋转

旋转前:

x0=rcosb,y0=rsinb

旋转后:

x1=rcos(b-a)=rcosbcosa+rsinbsina=x0cosa+y0sina

y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa

一般3-D旋转的变换。将一个空间点P绕一个中心点C旋转可用连续的3个变换来实现:

第1个变换:平移点C到坐标原点。

第2个变换:将P绕原点旋转。

第3个变换:平移点C回到原始位置。

本实验中要求旋转采用双线性插值法

如下为主要算法代码:

import math
import random
import cv2
import numpy as np
def bilinear_rotate(imgArray):
    H, W, channel = imgArray.shape
    pi = math.pi
    theta = random.randint(0,360)
    angle = theta * pi / 180
    matrix1 = np.array([[1, 0, 0],
                        [0, -1, 0],
                        [-0.5 * H, 0.5 * W, 1]])
    matrix2 = np.array([[math.cos(angle), -math.sin(angle), 0],
                        [math.sin(angle), math.cos(angle), 0],
                        [0, 0, 1]])
    matrix3 = np.array([[1, 0, 0],
                        [0, -1, 0],
                        [0.5 * H, 0.5 * W, 1]])
    new_data = np.zeros_like(imgArray,dtype=np.uint8)
    for i in range(H):
        for j in range(W):
            dot1 = np.matmul(np.array([i, j, 1]), matrix1)
            dot2 = np.matmul(dot1, matrix2)
            dot3 = np.matmul(dot2, matrix3)
            new_coordinate = dot3
            new_i = int(math.floor(new_coordinate[0]))
            new_j = int(math.floor(new_coordinate[1]))
            u = new_coordinate[0] - new_i
            v = new_coordinate[1] - new_j
            if new_j>=W or new_i >=H or new_i<1 or new_j<1 or (i+1)>=H or (j+1)>=W:
                continue
            if (new_i + 1)>=H or (new_j+1)>=W:
                new_data[i, j, :] = imgArray[new_i,new_j, :]
            else:
                new_data[i, j, :] = (1-u)*(1-v)*imgArray[new_i,new_j, :] + \
                                   (1-u)*v*imgArray[new_i,new_j+1, :] + \
                                   u*(1-v)*imgArray[new_i+1,new_j, :] +\
                                   u*v*imgArray[new_i+1,new_j+1, :]
    return new_data
image = cv2.imread('Asen.jpg')
new_image = bilinear_rotate(image)
cv2.imshow('Rotated image', new_image)

运行结果:
在这里插入图片描述

(3)缩放

缩放采用最邻近插值缩放

插值的目的是根据已知的图像的像素值获得未知目标图像的像素值

其中src表示原始图像,tar表示插值得到的目标图像,H和W分别表示图像的高度和宽度。插值的核心是找到(tar_x, tar_y)和(src_x, src_y)的映射关系,从而实现对目标图像的每一个像素点进行赋值。假设目的是将原始图像长度和宽度扩大(3,4)倍,即:

ratio_H = tar_H/src_H = tar_x/src_x = 3

ratio_W = tar_W/src_W = tar_y/src_y = 4

通过上式变形,得到目标图像的像素点和原始图像的像素点映射如下:

tar_x = src_x/ratio_H

tar_y = src_y/ratio_W

知道了像素点之间的映射关系,实现算法就很容易了,算法流程如下:

根据tar_H和tar_W创建目标图像

计算缩放比例因子ratio

遍历目标图像每个像素点,计算映射关系

遍历目标图像每个像素点,使用对应原始图像的对应像素点对其赋值

算法代码:

import cv2
import numpy as np

def test(img, Weight_out, Height_out):
    # 获取图像的大小
    Height_in, Weight_in, _ = img.shape
    # 创建输出图像
    outimg = np.zeros((Height_out, Weight_out, 3), dtype=np.uint8)

    for x in range(Height_out - 1):
        for y in range(Weight_out - 1):
            # 计算输出图像坐标(i,j)坐标使用输入图像中的哪个坐标来填充
            x_out = round(x * (Height_in / Height_out))
            y_out = round(y * (Weight_in / Weight_out))
            # 插值
            outimg[x, y] = img[x_out, y_out]
    return outimg


# 读取图像
img = cv2.imread('Asen.jpg')
test = test(img, int(img.shape[1] * 1.5), int(img.shape[0] * 1.5))
# OpenCV函数
OpenCV_test = cv2.resize(img, (int(img.shape[1] * 1.5), int(img.shape[0] * 1.5)))

cv2.imshow("nearest neighbor", test)  # 近邻插值缩放后
cv2.imshow("image", img)  # 原图
cv2.waitKey(0)

运行结果:
在这里插入图片描述

(4)镜像

opencv的函数flip()可以实现图像沿x轴翻转、沿y轴翻转、同时沿x轴和y轴翻转,从而实现图像的水平镜像和垂直镜像。

函数flip()的C++原型如下:

void cv::flip(InputArray src,

OutputArray dst,

int flipCode )

如果flipCode的值大于0,表示绕y轴翻转,对应于实现图像的水平镜像;
如果flipCode的值等于0,表示绕x轴翻转,对应于实现图像的垂直镜像;
如果flipCode的值小于0,表示同时绕x轴和y轴翻转,对应于同时实现图像的垂直镜像和水平镜像

运行结果:
在这里插入图片描述

四、实验心得

本次图像处理实验主要是对图像进行了灰度值的变化,以及平移、镜像、放大、旋转等操作。我使用的是python,python中的opencv库中包含许多丰富图像处理函数,我们可以方便的直接使用这些封装好的函数,但是对于我们学习这门课程的主要意义不仅仅是会进行图像处理,还要明白图像处理的原理,以及函数实现的过程。这就要求我们可以不使用库函数的情况下,自己编写相应的插值方法来实现图像的放大缩小等操作。总而言之,图像处理对我们生活方方面面影响巨大,我们学习这门课程要懂得图像处理原理,并运用于实践当中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值