人工智能导论:模型与算法,附录实验三:线性回归模型

news/2025/2/11 2:09:43/

本人研一,简单记录下上课的大作业,如果你不会自己写,相信你有缘能找到这篇博客

线性回归模型

1.实验内容

图像是一种非常常见的信息载体,但是在图像的获取、传输、存储过程中可能由于各种原因使得图像受到噪声的影响。如何去除噪声的影响,恢复图像原本的信息是计算机视觉中的重要研究问题。
常见的图像恢复算法有基于空间域的中值滤波、基于小波域的小波去噪、基于偏微分的非线性扩散滤波等。本次实验要对图像添加高斯噪声,并对添加噪声的图像进行基于线性回归模型的去噪

2.实验要求

(1) 生成受损图像
在这里插入图片描述

3.实验环境

可以基于Python的OpencCV库进行图像相关处理,使用Numpy库进行相关数值运算。

4.程序代码

废话不多说直接上代码

from matplotlib import pyplot as plt
import numpy as np
import cv2  # opencv库
from sklearn.linear_model import LinearRegression, Ridge, Lasso  # 回归分析def read_image(img_path):"""读取图片,图片是以 np.array 类型存储,返回图片的数组形式:param img_path: 图片的路径以及名称:return: img np.array 类型存储"""# 读取图片img = cv2.imread(img_path)# 如果图片是三通道,采用 matplotlib 展示图像时需要先转换通道if len(img.shape) == 3:img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转换围为二通道的灰度图return imgdef plot_image(image, image_title, is_axis=False):"""展示图像:param image: 展示的图像,一般是 np.array 类型:param image_title: 展示图像的名称:param is_axis: 是否需要关闭坐标轴,默认展示坐标轴:return:"""# 展示图片plt.imshow(image)# 关闭坐标轴,默认关闭if not is_axis:plt.axis('off')# 展示受损图片的名称plt.title(image_title)# 展示图片plt.show()def save_image(filename, image):"""保存图片,将np.ndarray 图像矩阵保存为一张 png 或 jpg 等格式的图片:param filename: 图片保存路径及图片名称和格式:param image: 图像矩阵,一般为np.array:return:无返回值"""# np.copy() 函数创建一个副本,复制到img变量中img = np.copy(image)# 从给定数组的形状中删除一维的条目fimg = img.squeeze()# 将图片数据存储类型改为 np.uint8if img.dtype == np.double:# 若img数据存储类型是 np.double ,则转化为 np.uint8 形式img = img * np.iinfo(np.uint8).max# 转换图片数组数据类型img = img.astype(np.uint8)  # .astype()将数据类型转换为括号的的类型img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)# 生成图片cv2.imwrite(filename, img)  # cv2.imwrite() 用于将图像保存到指定的文件def normalization(image):"""将数据线性归一化:param image: 图片矩阵,一般是np.array 类型:return: 将归一化后的数据,在(0,1)之间"""# 获取图片数据类型对象的最大值和最小值,比如int16范围[-32768,32768]info = np.iinfo(image.dtype)# 图像数组数据放缩在 0-1 之间,并转换为双精度return image.astype(np.double) / info.maxdef noise_mask_image(img, noise_ratio):"""生成受损图片:param img: 图像矩阵,一般为 np.ndarray:param noise_ratio: 噪声比率,可能值是0.4/0.6/0.8:return: noise_img 受损图片, 图像矩阵值 0-1 之间,数据类型为 np.array,数据类型对象 (dtype): np.double, 图像形状:(h,w,c),顺序为RGB"""# 受损图片初始化noise_img = None# -------------生成受损图像-----------------row, col = img.shape[0], img.shape[1]  # 图片高宽rgb = [None, None, None]  # rgb初始化for i in range(3):# 构造其中一个通道的噪声图for j in range(row):  # 第几行if rgb[i] is None:rgb[i] = np.random.choice(2, (1, col), p=[noise_ratio, 1 - noise_ratio])else:a = np.random.choice(2, (1, col), p=[noise_ratio, 1 - noise_ratio])  # 从0,1两个数根据概率,重复选择col次,列数,0为施加噪声rgb[i] = np.concatenate((rgb[i], a), axis=0)  # 将产生的噪声加到初始化的rgb上# 扩展 shapefor i in range(3):rgb[i] = rgb[i][:, :, np.newaxis]  # 变成三维# 合并rst = np.concatenate((rgb[0], rgb[1], rgb[2]), axis=2)  # 同个维度拼接noise_img = rst * img  # 噪声与原图逐元素相乘# -----------------------------------------------return noise_imgdef get_noise_mask(noise_img):"""获取噪声图像的矩阵形式,一般为 np.array:param noise_img: 带有噪声的图片:return: 噪声图像矩阵"""# 将图片数据矩阵只包含 0和1,如果不能等于 0 则就是 1。return np.array(noise_img != 0, dtype='double')def compute_error(res_img, img):"""计算恢复图像 res_img 与原始图像 img 的 2-范数,向量元素绝对值的平方和再开方:param res_img:恢复图像:param img:原始图像:return: 恢复图像 res_img 与原始图像 img 的2-范数"""# 初始化error = 0.0# 将图像矩阵转换成为np.narrayres_img = np.array(res_img)img = np.array(img)# 如果2个图像的形状不一致,则打印出错误结果,返回值为 Noneif res_img.shape != img.shape:print("shape error res_img.shape and img.shape %s != %s" % (res_img.shape, img.shape))return None# 计算图像矩阵之间的评估误差error = np.sqrt(np.sum(np.power(res_img - img, 2)))return round(error, 3)def restore_image(noise_img, size=4):"""使用区域二元线性回归模型 进行图像恢复。:param noise_img: 一个受损的图像:param size: 输入区域半径,长宽是以 size*size 方形区域获取区域, 默认是 4:return: res_img 恢复后的图片,图像矩阵值 0-1 之间,数据类型为 np.array,数据类型对象 (dtype): np.double, 图像形状:(height,width,channel), 通道(channel) 顺序为RGB"""# 恢复图片初始化,首先 copy 受损图片,然后预测噪声点的坐标后作为返回值。res_img = np.copy(noise_img)# 获取噪声图像noise_mask = get_noise_mask(noise_img)# -------------恢复图像----------------------------rows, cols, channel = res_img.shaperegion = 10  # 10 * 10的区域row_cnt = rows // regioncol_cnt = cols // regionfor chan in range(channel):for rn in range(row_cnt + 1):ibase = rn * regionif rn == row_cnt:ibase = rows - regionfor cn in range(col_cnt + 1):jbase = cn * regionif cn == col_cnt:jbase = cols - regionx_train = []y_train = []x_test = []for i in range(ibase, ibase + region):for j in range(jbase, jbase + region):if noise_mask[i, j, chan] == 0:  # 噪音点x_test.append([i, j])continuex_train.append([i, j])y_train.append([res_img[i, j, chan]])if x_train == []:print("x_train is None")continuereg = LinearRegression()reg.fit(x_train, y_train)pred = reg.predict(x_test)for i in range(len(x_test)):res_img[x_test[i][0], x_test[i][1], chan] = pred[i][0]res_img[res_img > 1.0] = 1.0res_img[res_img < 0.0] = 0.0# ---------------------------------------------------------------return res_imgif __name__ == "__main__":img_path = '12.jpg'  # 图片路径img = read_image(img_path)noise_ratio = 0.4  # 噪声比nor_img = normalization(img)print(nor_img.shape)# 生成受损图片for i in range(3):noise_img = noise_mask_image(nor_img, noise_ratio)# 保存受损图片save_image('result/damaged_' + str(noise_ratio) + '.png', noise_img)# 恢复图片res_img = restore_image(noise_img)# 保存恢复图片save_image('result/recovery_' + str(noise_ratio) + '.png', res_img)print("{}噪声比率,噪声图和原图之间的误差: {}".format(noise_ratio,compute_error(noise_img, nor_img)))print("{}噪声比率,恢复图和原图之前的误差: {}".format(noise_ratio,compute_error(res_img, nor_img)))noise_ratio = round(noise_ratio+0.2,3)# 展示恢复图片# plot_image(image=res_img, image_title="restore image")

直接拉到最后,看main函数,需要改的地方
在这里插入图片描述
总共4个地方需要改,根据你自己环境
第一个地方你图像的路径
第二个噪声比,这个可以不改,运行代码会依次生成0.4,0.6,0.8受损比例的图片
第三个为生成受损图片的保存路径
第四个为恢复图片的保存路径

注意:这里代码都写固定了,如果没能力就别乱改,你只需要改好路径,运行即可,很容易上手

5.实验结果

将路径改好后运行代码,会在result文件夹中生成6张图片,受损3张比例(0.4,0.6,0.8)图片,以及对应比例的恢复图3张
在这里插入图片描述
原图
在这里插入图片描述
受损图片,从左到右依次(0.4,0.6,0.8)
在这里插入图片描述
恢复图片,从左到右依次(0.4,0.6,0.8)

在这里插入图片描述

6.结束语

到这里实验就结束了,还是很简单的一个小实验
这里代码参考自一篇博客,但我进行了一些改进,让代码使用起来更加方便上手
https://blog.csdn.net/zhangpeterx/article/details/90262269


http://www.ppmy.cn/news/58521.html

相关文章

年薪40万程序员辞职炒股,把一年工资亏光了,得了抑郁症,太惨了

年薪40万的程序员辞职全职炒股 把一年的工资亏光了 得了抑郁症 刚才在网上看了一篇文章 是一位北京的一位在互联网 大厂上班的程序员 在去年就是股市行情比较好的时候 他买了30多万股票 结果连续三个月都赚钱 然后呢 他是就把每天就996这种工作就辞掉了 然后在家全是炒股 感觉炒…

Docker快速部署springboot项目

有很多开发者在项目部署过程中都会遇到一些繁琐的问题&#xff0c;比如打包、上传、部署等。而使用Docker可以非常方便地解决这些问题。在本文中&#xff0c;将详细讲解如何使用IDEA中的docker打包插件&#xff0c;将代码打包并直接发布到服务器上。这样&#xff0c;我们就可以…

JAVA入坑之GUI编程

一、相关概述 GUI编程是指通过图形化的方式来实现计算机程序的编写&#xff0c;它可以让用户通过鼠标、键盘等设备来操作计算机&#xff0c;而不是通过命令行来输入指令。在Java中&#xff0c;GUI编程主要使用的是Swing和AWT两种技术 二、AWT 2.1介绍 AWT是Java提供的用来建立…

Setting up SSH Host ...问题解决

一、问题可能原因&#xff1a; 网速问题导致下载过慢&#xff0c;超时 二、解决方式&#xff1a;手动下载安装 1、确定VSCode commit id&#xff0c;如下图所示 2、拼接请求&#xff0c;下载vscode server包 Arm&#xff1a;https://update.code.visualstudio.com/commit:换…

JavaScript中对象的定义、引用和复制

JavaScript是一种广泛使用的脚本语言&#xff0c;其设计理念是面向对象的范式。在JavaScript中&#xff0c;对象就是一系列属性的集合&#xff0c;每个属性包含一个名称和一个值。属性的值可以是基本数据类型、对象类型或函数类型&#xff0c;这些类型的值相互之间有着不同的特…

实战痛点:如何打包发布你的Vue 3应用

如何把开发好的代码部署到线上。 对于这个问题&#xff0c;你可能脱口而出&#xff1a;“使用npm run build就好了呀”。 这样做只是在本地把代码打包&#xff0c;如果想要在线上也可以访问这些代码&#xff0c;那么还需要加上部署的过程。 代码部署难点在 jQuery 时代之前&a…

算法记录lday4 LinkedList链表交换 删除倒数N个点 环形链表

今日任务 ● 24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点 ● 面试题 02.07. 链表相交 ● 142.环形链表II 两两交换链表中的节点 题目描述 Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modi…

电脑c盘满了变成红色了怎么清理?看看这7个方法

当C盘出现红色标识提示时&#xff0c;表示该分区的可用存储空间已经极度不足&#xff0c;可能会影响系统稳定性和性能。如果您需要清理C盘并腾出更多的存储空间&#xff0c;可以采取以下措施&#xff1a; 一、电脑c盘7种清理方法 方法1&#xff1a;清空回收站 演示机型&#…