scipy learn sharpen filter

news2024/9/20 14:25:34

文章目录

  • 1. 问题
  • 2. 方案
    • 2.1 学习一个 5 * 5的滤波核
    • 2.2 学习分通道的滤波核 以及 分离卷积
  • 3. 分析

根据图像对学习滤波核

之前研究过根据图像对生成3Dlut, 以及生成颜色变换系数

这里我们利用图像对学习 滤波

1. 问题

遇到的问题是这样的,已知一个图像和经过邻域滤波处理后的图像,想要求解这两个图像的滤波核

2. 方案

利用最小二乘法求解

这里以一对图像为例,src为锐化前,target为锐化后

在这里插入图片描述

ground truth滤波核为

    kernel_sharpen = np.array([[-1, -1, -1, -1, -1],
                                [-1, 2, 2, 2, -1],
                                [-1, 2, 8, 2, -1],
                                [-1, 2, 2, 2, -1],
                                [-1, -1, -1, -1, -1]])
    kernel_sharpen = kernel_sharpen / np.sum(kernel_sharpen)
    im2 = cv2.filter2D(im1, -1, kernel_sharpen)

2.1 学习一个 5 * 5的滤波核

原理很简单,直接利用scipy.optimize 的 least_squares函数求解
代码如下:

import cv2
import numpy as np
from scipy.optimize import least_squares


def min_fun_model_sr(x, im1, im2):
    x = x.reshape([5, 5])
    t = cv2.filter2D(im1, -1, x) - im2
    return t.reshape(-1)

import colour
def calc_deltaE(input_sRGB, ref_sRGB):
    """TODO: calculate deltaE 2000 with ref.
    :input_sRGB: target sRGB in linear domain, float [0, 1]
    :ref_sRGB: ref. sRGB in linear domain, float[0, 1]
    :returns: delta E 2000 between target and reference
    """
    XYZ = colour.sRGB_to_XYZ(input_sRGB, apply_cctf_decoding=True)
    ref_XYZ = colour.sRGB_to_XYZ(ref_sRGB, apply_cctf_decoding=True)
    Lab = colour.XYZ_to_Lab(XYZ)
    ref_Lab = colour.XYZ_to_Lab(ref_XYZ)
    delta_E = colour.delta_E(Lab, ref_Lab)
    # print('deltaE 2000: {}'.format(delta_E))
    return delta_E

if __name__ == "__main__":
    src = r'D:\superresolution\sharpen\learn_filter\\20221025101435_bicubic.png'
    target = r'D:\superresolution\sharpen\learn_filter\\20221025101435_bicubic_shaprpen_edge2.png'

    im1 = cv2.imread(src)
    h, w, c = im1.shape
    print(h,w,c)
    im2 = cv2.imread(target)

    # # generating the kernels
    # kernel_sharpen = np.array([[-1, -1, -1, -1, -1],
    #                            [-1, 2, 2, 2, -1],
    #                            [-1, 2, 8, 2, -1],
    #                            [-1, 2, 2, 2, -1],
    #                            [-1, -1, -1, -1, -1]])
    # kernel_sharpen = kernel_sharpen / np.sum(kernel_sharpen)
    # im2 = cv2.filter2D(im1, -1, kernel_sharpen)


    # im3 = cv2.resize(im1, (h//2, w//2) )
    # im4 = cv2.resize(im2, (h//2, w//2) )
    print(im1.shape, im2.shape)
    # 先中值滤波一下,避免噪声像素的影响, 滤波后生成的3Dlut 产生的图像可能会有一丢丢的模糊效果。
    # rgb = cv2.medianBlur(im3, 3).reshape(-1, 3)
    # srgb = cv2.medianBlur(im4, 3).reshape(-1, 3)
    rgb = im1/ 255
    srgb = im2/ 255

    print('lq method ret:\n')
    len = 5
    filter = np.random.uniform(0, 1, [len, len]).reshape(-1)
    print('init filter:', filter)
    res = least_squares(min_fun_model_sr, filter, bounds=(-1, 2), args=(rgb, srgb), verbose=1)
    kernel = res.x.reshape(len, len)


    # apply
    # file = r'd.jpeg'
    # im0 = cv2.imread(file)
    im_t = im1 / 255
    im_t1 = cv2.filter2D(im_t, -1, kernel)

    a3 = np.clip(im_t1 * 255, 0, 255).astype(np.uint8)
    np.set_printoptions(suppress=True)
    cv2.imwrite(src[:-4] + '_filter_gen.png', a3)
    np.savetxt(src[:-4] + '_filter_gen.txt', kernel, fmt='%.05f')

    print(np.round(kernel, 3), np.sum(kernel))

2.2 学习分通道的滤波核 以及 分离卷积


# 实现分通道卷积
def model(kernel, im):
    filtered_image2 = np.zeros_like(im)
    # print(kernel.shape, im.shape)
    kernel = kernel.reshape(5, 5, 3)
    filtered_image2[..., 0] = ndimage.convolve(im[..., 0], kernel[..., 0], mode='nearest')
    filtered_image2[..., 1] = ndimage.convolve(im[..., 1], kernel[..., 1], mode='nearest')
    filtered_image2[..., 2] = ndimage.convolve(im[..., 2], kernel[..., 2], mode='nearest')
    return filtered_image2  # N*11 , 11*3 -> N * 3

# 实现分通道卷积后再融合, 类似depth-wise卷积
def model2(para, im):
    ks = 5
    k_int = 3
    k_out = 3
    t1 = ks*ks*k_int*k_out
    kernel = para[:t1]
    kernel = kernel.reshape(ks, ks, k_int, k_out)

    kernel1 = kernel[..., 0]
    out1 = model(kernel1, im)
    kernel2 = kernel[..., 1]
    out2 = model(kernel2, im)
    kernel3 = kernel[..., 2]
    out3 = model(kernel3, im)

    rat = para[t1:]
    ret = np.zeros_like(im)
    ret[..., 0] = rat[0] * out1[..., 0] + rat[1] * out1[..., 1] + rat[2] * out1[..., 2]
    ret[..., 1] = rat[3] * out2[..., 0] + rat[4] * out2[..., 1] + rat[5] * out2[..., 2]
    ret[..., 2] = rat[6] * out3[..., 0] + rat[7] * out3[..., 1] + rat[8] * out3[..., 2]

    return ret  # N*11 , 11*3 -> N * 3

# 定义函数, 不需要自己写损失函数,在调用函数的时候可以指定损失函数类型
def min_fun_model_sr_split_conv(x, rgb, target):
    t = model(x, rgb)

    t -= target
    # t = np.linalg.norm(t, ord=2, axis=1)
    return t.reshape(-1)  # 需要是1维数组

def min_fun_model_sr_split_conv_merge(x, rgb, target):
    t = model2(x, rgb) - target
    # t = np.linalg.norm(t, ord=2, axis=1)
    return t.reshape(-1)  # 需要是1维数组

def min_fun_model_sr(x, im1, im2):
    x = x.reshape([5, 5])
    t = cv2.filter2D(im1, -1, x) - im2
    return t.reshape(-1)


if __name__ == "__main__":
    src = r'D:\superresolution\sharpen\cubic\20221025101435_bicubic.png'
    target = r'D:\superresolution\sharpen\cubic\20221025101435_bicubic_shaprpen_edge.png'

    im1 = cv2.imread(src)
    h, w, c = im1.shape
    print(h,w,c)
    im2 = cv2.imread(target)

    # generating the kernels
    kernel_sharpen = np.array([[-1, -1, -1, -1, -1],
                               [-1, 2, 2, 2, -1],
                               [-1, 2, 8, 2, -1],
                               [-2, 2, 2, 2, -1],
                               [-1, -1, -1, -1, -1]])
    kernel_sharpen = kernel_sharpen / np.sum(kernel_sharpen)
    # process and output the image
    im2 = cv2.filter2D(im1, -1, kernel_sharpen)


    im3 = cv2.resize(im1, (h//2, w//2))
    im4 = cv2.resize(im2, (h//2, w//2))
    print(im1.shape, im2.shape)
    # 先中值滤波一下,避免噪声像素的影响, 滤波后生成的3Dlut 产生的图像可能会有一丢丢的模糊效果。
    # rgb = cv2.medianBlur(im3, 3).reshape(-1, 3) / 255
    # srgb = cv2.medianBlur(im4, 3).reshape(-1, 3) / 255
    rgb = im3/ 255
    srgb = im4/ 255

    print('lq method ret:\n')
    len = 5
    # filter = np.random.uniform(0, 1, [len, len]).reshape(-1)
    # print('init filter:', filter)
    # res = least_squares(min_fun_model_sr, filter, bounds=(-1, 2), args=(rgb, srgb), verbose=1)

    filter = np.random.uniform(0, 1, [len *len* 3* 3 + 9]).reshape(-1)
    print('init filter:', filter)
    res = least_squares(min_fun_model_sr_split_conv_merge, filter, bounds=(-1, 2), args=(rgb, srgb), verbose=1)
    para = res.x



    # apply
    # file = r'd.jpeg'
    # im0 = cv2.imread(file)
    im_t = im1 / 255
    # method 1
    #im_t1 = cv2.filter2D(im_t, -1, kernel)
    # mothod 2
    # im_t1 = model( kernel, im_t)
    # method 3
    im_t1 = model2(para, im_t)
    a3 = np.clip(im_t1 * 255, 0, 255).astype(np.uint8)
    cv2.imwrite(src[:-4] + '_filter_gen_split_merge.png', a3)

    np.set_printoptions(suppress=True)
    print(np.round(para, 3), np.sum(para[:75*3]))
    print(kernel_sharpen, np.sum(kernel_sharpen))

3. 分析

通过以上3个model都可以优化得到相关参数,3个model的结果差距不大,和groundtruth 效果比较锐化效果减弱。

因此训练的时候,1. 对target 进行增强 2. 可以利用更多图像来 学习 filter.

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182821.html

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

相关文章

爱快软路由对笔记本实现网络唤醒

本人有一台爱快软路由作为动态域名和端口映射,实现通过阿里域名远程访问内网设备。一台X201笔记本连接在软路由上。由于X201电池已经卸下无法实现来电开机,只能通过爱快e云APP手动实现网络唤醒,感觉非常麻烦。爱快云web端也不能实现开机唤醒X…

学长教你学C-day11-C语言结构体、枚举、联合体

“前面我们学习了数组,从数据类型来看,数组就是具有相同数据类型的变量集合;从内存空间来看,数组就是一串由相同大小的数据空间组成的较大的内存空间。那么结构体是什么呢?从内存角度讲,结构体也是一块地址…

PEG化芘衍生物——Pyrene-PEG-Acid,Pyrene-PEG-COOH,芘丁酸-聚乙二醇-羧基

一:产品描述 1、名称 英文:Pyrene-PEG-COOH,Pyrene-PEG-Acid 中文:芘丁酸-聚乙二醇-羧基 2、CAS编号:N/A 3、所属分类: Carboxylic acid PEG Pyrene PEG 4、分子量:可定制2000、1000、340…

2022个人年度总结:别让内心的烦躁和焦虑,占据本就不多的热情。

在从毕业一直到现在,我都会写一篇关于自己的从技术、商业、人情世故以及未来展望的博文,以至于归纳每个时期的自己, 走在互联网开发的边缘,不得不抽出时间鞭策自己学习新知识,未知的知识是 充满好奇的, 就好…

Makefile学习⑧:Makefile中通用部分做公共头文件

Makefile学习⑧:Makefile中通用部分做公共头文件 创建2个文件夹Demo1和Demo2,2个文件夹中的文件完全一样,但是命名不一样。 博主创建的如下,内容沿用前几章的函数文件。 这两个Makefile中的内容除了目标文件名和依赖文件名不一致&#xff0…

轻松实现一个Python+Selenium的自动化测试框架

首先你得知道什么是Selenium? Selenium是一个基于浏览器的自动化测试工具,它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。Selenium主要包括三部分:Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE&#xff…

知识抽取-实体及关系抽取

信息抽取的三个最重要,最受关注的子任务: 实体抽取 命名实体识别,包括实体检测(find)和分类(classify) 关系抽取。 通常我们所述的三元组抽取, 一个谓词(predicate)带2个形参(argum…

MySQL学习记录(9)存储引擎

文章目录6、InnoDB存储引擎6.1、逻辑存储结构6.2、架构6.2.1、概述6.2.2、内存结构6.2.3、磁盘结构6.2.4、后台线程6.3、事务原理6.3.1、事务基础6.3.2、redo log日志6.3.3、undo log日志6.4、MVCC6.4.1、基本概念6.4.2、记录中隐藏字段6.4.3、undo log日志6.4.4、readview6.4.…

算法基础(二):数组知识点及题型讲解

算法基础(二):数组知识点及题型讲解1 数组定义2 Python数组常用操作2.1 创建数组2.2 添加元素2.3 访问元素2.4 更新元素2.5 删除元素2.6 获取数组长度2.7 遍历数组2.8 查找某个元素2.9 数组排序3 力扣题目训练一些算法基础知识点和leetcode题…

汇编语言1基础知识

机器语言 机器语言是机器指令的集合,即计算机可以执行的指令。 机器指令由一连串二进制数字构成,计算机中用高低电平表示。高电平为1,低电平为0。 早期通过在纸带上打孔输入计算机运算。打孔为1,不打孔为0。 上图出自剧版三体第…

c语言tips-【gcc详细介绍】

0. 什么是gcc GCC 原名为 GNU C语言编译器(GNU C Compiler)GCC(GNU Compiler Collection,GNU编译器套件)是由 GNU 开发的编程语言译器。 GNU编译器套件包括C、C、 Objective-C、 Java、 Ada 和 Go语言前端&#xff0c…

【GPLT 二阶题目集】L2-009 抢红包

没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。 输入格式: 输出格式: 按照收入金额从高到低的递减顺序输出每个人的编号和收入金额(以元为单位,输出小数点后2位&a…

ISIS与OSPF的双点双向简介与配置,双点双向中存在的问题(次优路径与环路风险)

2.4.0 ISIS与OSPF的双点双向简介与配置,双点双向中存在的问题 关于双点双向的相关概念 单点双向 网络中连接外网的设备称为出口网关设备 ,通常小型网络中仅有一台出口网关设备。 网络中仅存在一台出口设备与外网设备对接时相互引入对端的路由&#xf…

学长教你学C-day12-C语言函数

不知不觉,小刘已经讲了十一天C语言了,语法、数据结构、数组、结构体、指针的概念和使用大家都已经了然于心,但是想用C语言开发一个有用的程序还需要一个很关键的部分,那就是编写“函数”。 “函数这个名字大家肯定都不陌生&#x…

ZooKeeper架构篇 - 分布式协调服务ZooKeeper

前言 本文基于 ZooKeeper 3.8.0 版本。 ZooKeeper集群搭建 准备四台服务器,IP地址分别为10.211.55.6、10.211.55.7、10.211.55.8、10.211.55.9 下载并解压 ZooKeeper 文件,四台服务器进入 data 目录分别创建一个 myid 文件,文件内容分别为…

vue全家桶(二)组件化开发

vue全家桶(二)组件化开发1.组件化开发思想2.组件注册2.1局部注册2.2全局注册Vue.component1.注意事项:2.组件的命名方式3.组件间的交互3.1父组件向子组件传值-props属性值类型1.组件化开发思想 标准分治重用组合 2.组件注册 vue 注册组件的…

《动手学深度学习》笔记一 ------机器学习中的基础概念

写在前面:本文按照书中的脉络做的笔记,包含概念的定义、自己的理解以及阅读时的小思考。感受:深度学习很奥妙,很有趣! 1.2机器学习中的关键组件 可以⽤来学习的数据(data);如何转换…

直接在Notepad++中运行GO语言

建议先阅读并实践(配置notepad支持go语言语法着色(高亮)):https://mp.csdn.net/mp_blog/creation/editor/new/1287591911.Windows上安装Go语言开发包参考链接:http://c.biancheng.net/view/3992.html1.1.下载Go语言开发包可以在Go语言官网 &a…

大聪明教你学Java | 深入浅出聊 Mybatis 的一级缓存和二级缓存

前言 🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。 🍊支持作者: 点赞👍、关注💖、留言&#x1f4…

【头歌】函数的递归调用

第1关:编写递归函数方法求x的n次方 (要求n>0)任务描述本关任务:编写递归函数方法求x的n次方 (要求n>0)。相关知识递归法在定义一个过程或函数时出现调用本过程或本函数的成分,称之为递归。若调用自身,称之为直接递归。若过程…