美文网首页
Python OpenCV 图像的 最近邻插值 与 双线性插值算

Python OpenCV 图像的 最近邻插值 与 双线性插值算

作者: 梦想橡皮擦 | 来源:发表于2021-12-10 14:28 被阅读0次

Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧。本篇博客是这个系列的第 43 篇。
该系列文章导航参考:https://blog.csdn.net/hihell/category_10688961.html

基础知识铺垫

先补齐一下昨天文章发布出去的一个小坑,最后一段代码实现之后,发现运行之后图像边缘出现了很多锯齿。

20210217211831100[1].png

疑惑的同时,肯定是代码有细节弄差了,复查代码的时候发现问题了,注意下述代码:

dst[dst_y, dst_x, n] = (1-u)*(1-v)*src[j, i, n]+u*(1-v) * src[j+1, i, n] + (1-u)*v*src[j, i+1, n] + u*v*src[j+1, i+1, n]

与公式比对,这个细致的活你可以自己比对一下。
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)

问题出在图像的行与列上,代码的 u*(1-v) * src[j+1, i, n] + (1-u)*v*src[j, i+1, n] 这个部分我写反了~尴尬

修改成下述代码,搞定,基本一模一样了。

dst[dst_y, dst_x, n] = (1-u)*(1-v)*src[j, i, n]+v*(1-u) * src[j+1, i, n] + (1-v)*u*src[j, i+1, n] + u*v*src[j+1, i+1, n]
20210217212140837[1].png

算法优化

下面说一下算法优化吧,咱还在 这篇博客 挖下了一个小坑,最近邻插值算法最终的结果不尽人意,图像在放大的时候出现了很强的锯齿。

20210217212454103[1].png

先把之前的代码迁移过来,修改成如下格式:

import cv2 as cv
import numpy as np


def nearest_demo(src, multiple_y, multiple_x):
    src_y, src_x, src_c = src.shape
    tar_x, tar_y, tar_c = src_x*multiple_x, src_y*multiple_y, src_c
    # 生成一个黑色的目标图像
    tar_img = np.zeros((tar_y, tar_x, tar_c), dtype=np.uint8)
    print(tar_img.shape)
    # 渲染像素点的值
    # 注意 y 是高度,x 是宽度
    for y in range(tar_y-1):
        for x in range(tar_x-1):
            # 计算新坐标 (x,y) 坐标在源图中是哪个值

            src_y = round(y*src_y/tar_y)
            src_x = round(x*src_x/tar_x)

            tar_img[y, x] = src[src_y, src_x]

    return tar_img


src = cv.imread("./ttt.png")
print(src.shape)
cv.imshow("src", src)
# dsize = (cols,rows) 中文,(宽度,高度)
dst = cv.resize(src, (src.shape[1]*2, src.shape[0]
                      * 2), interpolation=cv.INTER_NEAREST)
cv.imshow("dst", dst)

new_dst = nearest_demo(src, 2, 2)
cv.imshow("new_dst", new_dst)

cv.waitKey(0)
cv.destroyAllWindows()

第一部分的优化是关于中心点的,这部分说真的,橡皮擦找了很多资料,发现都解释的不太清楚,基本就是到重点的地方就略过了,大意我在进行转述一遍,如果你有好的解释,欢迎在评论区提供给我,重点就是那 0.5 像素的问题。

上文代码如果想实现和 OpenCV 提供的内置函数一样的效果,重点修改的地方如下:

srcy = round(y*src_y/tar_y)
srcx = round(x*src_x/tar_x)
# 修改如下
srcy = round((y+0.5)*src_y/tar_y-0.5)
srcx = round((x+0.5)*src_x/tar_x-0.5)

就是在这个地方直接懵掉了,有的博客中写道 srcX=dstX* (srcWidth/dstWidth)+0.5*(srcWidth/dstWidth-1) 相当于我们在原始的浮点坐标上加上了0.5*(srcWidth/dstWidth-1)

但是这个地方没有其它解释了,有的博客会用两张图对比着说要源图像与目标图像的几何中心对齐,但是也只是画了两张图加上一些简单的文字描述,摘抄如下:

假设源图像是 3x3,这个图像的中心点坐标为 (1,1),目标图像为 9x9,中心点坐标是 (4,4),那中心点对齐就应该指的是 (4,4) 点对齐到 (1,1) 点,但是根据 srcx = round(x*src_x/tar_x)srcy = round(y*src_y/tar_y) 公式计算,得到的中心点坐标是 (1.333,1.333) 并不是 (1,1),图像整体偏右下方,现在需要对齐。

那我们进行一下简单的推算。中心点对齐提前假设源图像不动,那最终应该是存在下列公式。

源图像 src 中心点坐标 (\cfrac{M-1}{2},\cfrac{M-1}{2}),目标图像 dst 中心点坐标 (\cfrac{N-1}{2},\cfrac{N-1}{2})

将上述值带入公式: srcx=dstx*(\cfrac{srcwidth}{dstwidth})+K

式子转换成 \cfrac{M-1}{2}=\cfrac{N-1}{2}*\cfrac{M}{N}+K

最后求得 K 的值为 \cfrac{1}{2}*(\cfrac{M}{N}-1)

\cfrac{M}{N}=\cfrac{srcwidth}{dstwidth}

所以 K 其实等于 K=\cfrac{1}{2}*(\cfrac{srcwidth}{dstwidth}-1)

对应到代码上,就变成了如下内容:

# 修改前
src_y = round(dst_y*src_height/tar_height)
src_x = round(dst_x*src_width/tar_width)
# 修改后
src_y = round(dst_y*src_height/tar_height+1/2*(src_height/tar_height-1))
src_x = round(dst_x*src_width/tar_width+1/2*(src_height/tar_height-1))

其实这时你在这里一下,就得到最终的结果了。

# 修改后
src_y = round((dst_y+0.5)*src_height/tar_height-0.5)
src_x = round((dst_x+0.5)*src_width/tar_width-0.5)

修改之后,运行感觉比系统内置的效果还出色一些了,哈哈哈。

20210218154827642[1].png

相同的优化复制到双线性插值算法中,自己可以对比一下运行的效果。

关于运行速度,我也找了一些资料,奈何目前掌握的基础知识不够,目前先搁置一下吧,这个系列过 100 篇的时候,我们在聊。

橡皮擦的小节

真没有想到,一个 0.5 像素的小问题竟然这么费力。

希望今天的 1 个小时你有所收获,我们下篇博客见~

相关阅读


技术专栏

  1. Python 爬虫 100 例教程,超棒的爬虫教程,立即订阅吧
  2. Python 爬虫小课,精彩 9 讲

相关文章

  • Python OpenCV 图像的 最近邻插值 与 双线性插值算

    Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧。本篇博客是这个系列的第 43 篇。该系...

  • 28. 图像缩放

    插值方法 四种插值,最近邻域插值 双线性插值 像素关系重采样 立方插值其中最近邻域插值、双线性插值原理如下: 1)...

  • 【图像缩放算法】双立方(三次)插值

    当我们进行图像缩放的时候,我们就需要用到插值算法。常见的插值有: 最邻近插值 双线性插值 双立方(三次)插值在这三...

  • 图像插值算法和OpenCV框架

    1 算法理论介绍与推荐 1.1 最近邻插值算法原理 最近邻插值,是指将目标图像中的点,对应到源图像中后,找到最相...

  • 图像缩放小记

    算法AndroidJniBitmapOperations演示了最邻近插值法和双线性插值法来做图像缩放。这个项目里的...

  • 视觉笔试刷题_1_索贝公司_2019-08-10

    填空题 常用的插值算法:双线性插值、立方卷积插值、最近邻插值 常用的边缘检测算子:canny、sobel、Robe...

  • 图形图像处理算法(3)---- 图形缩放算法

    图形的缩放的需求很普遍也很好理解,就是图形的放大和缩小图形缩放的算法主要分为两种 : 最近邻插值算法 双线性插值算...

  • 图像处理|插值

    opencv interpolation 选项 所用的插值方法INTER_NEAREST 最近邻插值IN...

  • 图像插值

    最临近插值 最近邻插值在图像放大时补充的像素取最临近的像素的值。由于方法简单,所以处理速度很快,但是放大图像画质劣...

  • 【数学】线性插值

    线性插值有一阶、二阶、三阶,对应为单线性插值、双线性插值和三线性插值。三者皆为线性插值,不同之处在于单线性插值为2...

网友评论

      本文标题:Python OpenCV 图像的 最近邻插值 与 双线性插值算

      本文链接:https://www.haomeiwen.com/subject/xjmcfrtx.html