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

news2024/11/25 22:55:08

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

线性回归模型

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 img


def 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)

    # 从给定数组的形状中删除一维的条目f
    img = img.squeeze()

    # 将图片数据存储类型改为 np.uint8
    if 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.max


def 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上

    # 扩展 shape
    for 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_img


def 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.narray
    res_img = np.array(res_img)
    img = np.array(img)

    # 如果2个图像的形状不一致,则打印出错误结果,返回值为 None
    if 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.shape
    region = 10  # 10 * 10的区域
    row_cnt = rows // region
    col_cnt = cols // region

    for chan in range(channel):
        for rn in range(row_cnt + 1):
            ibase = rn * region
            if rn == row_cnt:
                ibase = rows - region
            for cn in range(col_cnt + 1):
                jbase = cn * region
                if cn == col_cnt:
                    jbase = cols - region
                x_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])
                            continue
                        x_train.append([i, j])
                        y_train.append([res_img[i, j, chan]])
                if x_train == []:
                    print("x_train is None")
                    continue
                reg = 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.0
    res_img[res_img < 0.0] = 0.0
    # ---------------------------------------------------------------

    return res_img


if __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.coloradmin.cn/o/478013.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

程序员如何通过创作图文项目实现自己的代码价值

本文阅读适合人群&#xff1a; 1.程序员 2.图文赛道创业者 项目背景&#xff1a; 毫无疑问&#xff0c;这是一个优质内容的时代&#xff0c;从某种意义上说&#xff0c;优质内容Money。优质内容的形式包含很多&#xff0c;在头条的定义中包括&#xff1a;纯文字&#xff08;…

存储资源调优技术——SmartTier智能分级技术、SmartQoS智能服务质量控制技术

目录 SmartTier智能分级技术 基本概述 工作原理 实现SmartThier数据迁移的三个阶段 应用场景 SmartQoS智能服务质量控制 基本概念 两种关键技术 应用场景 SmartTier智能分级技术 基本概述 自动将不同活跃的数据和不同特点的存储介质动态匹配&#xff0c;提高性能。 NL…

ETL工具 - Kettle 转换算子介绍

一、Kettle 转换算子 上篇文章对 Kettle 中的输入输出算子进行了介绍&#xff0c;本篇文章继续对转换算子进行讲解。 下面是上篇文章的地址&#xff1a; ETL工具 - Kettle 输入输出算子介绍 转换是ETL里面的T&#xff08;Transform&#xff09;&#xff0c;主要做数据转换&am…

开放式基金净值估算数据 API 数据接口

开放式基金净值估算数据 API 数据接口 全量基金数据&#xff0c;实时数据&#xff0c;所有基金数据。 1. 产品功能 返回实时开放式基金净值估值可定义所有基金估值数据&#xff1b;多个基金属性值返回&#xff1b;多维指标&#xff0c;一次查询毫秒级返回&#xff1b;数据持续…

领域驱动设计事件驱动框架命令查询责任分离测试驱动开发

领域驱动设计: DDD 事件驱动框架: Event Driven Architecture 命令查询责任分离: CQRS(Command Query Responsibility Segregation) 测试驱动开发: TDD 先睹为快&#xff1a;架构图 入口&#xff1a;entrypoint 入口是系统外部客户访问系统内部的端口。常见的入口如http, …

算法刷题|647.回文子串、516.最长回文子序列

回文子串 题目&#xff1a;给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&#xff0c;即使是由相同的字符…

【redis】redis分布式锁(三)自动续期

系列文章目录 【redis】redis分布式锁&#xff08;一&#xff09;手写分布式锁1.0~6.0 【redis】redis分布式锁&#xff08;二&#xff09;可重入锁设计模式 文章目录 系列文章目录前言一、CAPredis集群 APZooKeeper集群 CP 数据一致性Eureak集群 APnacos集群 AP 二、lua脚本脚…

1 认识仿真工具Packet Tracer【实验】【计算机网络】

1 认识仿真工具Packet Tracer【实验】【计算机网络】 前言推荐1 认识仿真工具Packet Tracer1.1账号注册与Packet Tracer软件下载1.1.1 下载1.1.2 安装 1.2 Packet Tracer界面简介1.2.1 总述1.2.2 详细 1.3网络拓扑构建与设备模块添加1.3.1如何往工作区中添加设备1.3.2添加连线1…

【计算机网络】1.1——因特网概述

因特网概述&#xff08;了解&#xff09; 网络、互联网和因特网 网络由若干结点和连接这些结点的链路组成 多个网络还可以通过路由器互连起来&#xff0c;互联网是"网络的网络“ internet 和 Internet internet&#xff08;互联网或互连网&#xff09;是通用名词 泛指…

Java 基础入门篇(四)——— 方法的重载与参数传递机制

文章目录 一、方法的定义二、方法的参数传递机制 ★2.1 基本类型的参数传递2.2 引用类型的参数传递 三、方法重载 一、方法的定义 方法的作用&#xff1a;封装一段代码的语法结构&#xff0c;可以被重复调用&#xff0c;以此提高代码的复用性&#xff0c;提高开发效率&#xf…

操作系统之线程

线程 一、产生原因 最开始的并发&#xff0c;只能更具切换进程的方式去交替执行进程来宏观上并发&#xff0c;但是切换进程需要切换执行进程的环境&#xff0c;有很大的系统开销&#xff0c;所以产生了线程&#xff0c;让其可以不用频繁的切换进程&#xff0c;使得线程成为CPU…

【论文笔记 fintune 】羊驼

1.论文 这些开发由两个关键组件提供动力&#xff1a;大型预训练语言模型&#xff08;LM&#xff09;和人工编写的指令数据。 1.1 背景 目前的训练太吃数据了&#xff0c;需要使用一些替代方法减少对数据的依赖有微调过的数据集效果远好于没有微调 用什么数据集微调呢&#x…

Collaborative Metric Learning(www 2017)

Background 传统基于MF的模型&#xff0c;将特征向量的点积作为预测结果&#xff0c;这存在一个很大的问题&#xff0c;即dot product 不满足三角不等式&#xff09;&#xff0c;这会导致学到的特征向量次优&#xff08;难以捕捉用户细粒度的偏好&#xff09;。本文提出了一种…

【Java笔试强训 20】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;字符串反…

第十八章 协程

我们知道脚本都是继承自MonoBehaviour类&#xff0c;而其中的Update方法里面放置了大部分的游戏逻辑处理代码。Update方法是游戏循环的每一帧都去执行&#xff0c;这就要求我们的代码“无时无刻”不在处理所有的可能发生的情况&#xff0c;并做出相应的处理。如果我们想要完成“…

Vue之render函数

概述 render函数从名字上看就可以看出&#xff0c;它是一个用于渲染的函数&#xff0c;在Vue中我们要将我们写的界面展示到屏幕上时&#xff0c;使用的方式都是组件中的template:标签下编写内容后&#xff0c;由Vue将我们编写的界面渲染到屏幕上。而这个render函数就是比templ…

B. Divide Candies(数学 + 思维)

Problem - B - Codeforces Arkady和他的朋友们喜欢在一个n n的棋盘上玩跳棋。这个棋盘的行和列从1到n编号。 他的朋友们最近赢了一场比赛&#xff0c;所以Actady想用一些糖果来取悦他们。记得一则古老寓言(但不记得寓意)》&#xff0c;Arlady想给他的朋友们每个格子一个糖果组…

SpringMVC学习总结(一)SpringMVC简介入门案例

SpringMVC学习总结&#xff08;一&#xff09;SpringMVC简介/入门案例 一、SpringMVC简介 &#xff08;一&#xff09;什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分。 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的Ja…

手把手教你学会gitee的注册和代码的提交

欢迎来到壮壮的代码世界 gitee的注册和提交 一、gitee是什么&#xff1f;二、gitee怎么注册三、gitee的一些基本配置四、在gitee上创建远程仓库&#xff08;存储代码的地方&#xff09;五、clone远程仓库到本地电脑六、怎么把本地的代码推送到远程仓库去&#xff08;git的三板斧…

jQuery操作

文章目录 1. jQuery基本介绍1.1 原理示意图1.2 快速入门1.2 什么是jquery对象1.3 dom对象转jQuery对象1.4 jQuery对象转dom对象1.5 jQuery选择器1.5.1 jQuery基本选择器1.5.2 jquery层次选择器1.5.3 基础过滤选择器1.5.4 内容过滤选择器1.5.5 可见度过滤选择器1.5.6 属性过滤选…