Python OpenCV 图像的几何变换,先说不平凡的 resize 函数[通俗易懂]

interplolation最近邻插值算法说明

大家好,又见面了,我是你们的朋友全栈君。

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

基础知识铺垫

在 OpenCV 中常见的几何变换有缩放,仿射,透视变换,之前的内容中已经学习过缩放函数了,今天一边复习旧知识,一边学习新知识。

先看一下三个几何变换对应的函数原型是:

dst = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
dst = cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
dst = cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])

先从缩放说起,函数名为 cv2.resize(),非空参数有 2 个,分别是 srcdsize,含义为源图像与缩放后图像的尺寸。

import cv2 as cv

src = cv.imread("./t1.jpg")
cv.imshow("src", src)
dst = cv.resize(src, (200, 200))
cv.imshow("dst", dst)
cv.waitKey(0)
cv.destroyAllWindows()

上述为最简单的代码,运行效果如下,实现了一个简单的变化
Python OpenCV 图像的几何变换,先说不平凡的 resize 函数
该案例会出现一个常见的错误,缩放的数值提供的是浮点类型,错误提示为

TypeError: integer argument expected, got float

还有需要注意的是,元组 dsize 的两个值说明如下,顺序不要记错。

# dsize = (cols,rows) 中文,(宽度,高度)
dst = cv.resize(src, (400, 200))

这个地方深究下去,其实需要记忆的细节很多,例如在笛卡尔坐标系里面,记录一个坐标点都是先 x 轴,后 y 轴,但是在计算机中,图像是以矩阵的形式保存的,先行后列,所以 宽x高x通道 的图片会保存在 高x宽x通道的三位数组中,在图像处理的时候,都是按照 高x宽x通道记忆,例如通过 shape 获取形状。

src = cv.imread("./t1.jpg")
print(src.shape)

输出的结果就是 (高,宽,通道),但是这一点 resize 函数没有遵守,它依旧采用的是 (宽,高) 设置。

fxfy为图像x,y方向的缩放比例,使用该参数,需要提前将 dsize 设置为 (0,0),测试代码如下:

import cv2 as cv

src = cv.imread("./t1.jpg")
print(src.shape)
cv.imshow("src", src)
# dsize = (cols,rows) 中文,(宽度,高度)
dst = cv.resize(src, (0, 0),fx=0.5,fy=0.5)
cv.imshow("dst", dst)
cv.waitKey(0)
cv.destroyAllWindows()

测试结果为,如果不提前设置 dsize(0,0),那 fxfy 不会生效。注意 dsize=(0,0),如果数据类型不对,会出现如下错误:

SystemError: new style getargs format but argument is not a tuple

Python OpenCV 图像的几何变换,先说不平凡的 resize 函数

interplolation 缩放时的插值方式

interplolation 为缩放时的插值方式,有以下几种方式,这些是今天要探索的重点内容。

  • cv.INTER_NEAREST:最近邻插值;
  • cv.INTER_LINEAR:双线形插值(默认设置);
  • cv.INTER_CUBIC:4×4 像素邻域的双三次插值;
  • cv2.INTER_AREA:基于局部像素的重采样。它可能是图像抽取的首选方法,因为它会产生无云纹理的结果。 但是当图像缩放时,它类似于 INTER_NEAREST 方法。

最近邻插值

这部分比较吃精力,所以今天这一个小时,我们争取搞定一个插值算法,即最近邻插值就好。

这个算法的思想是,通过已经像素值去获取目标像素值。我在学习的时候找到最通俗的解释,接下来由我说明给你。

假设有一个 3×3 的灰度图,需要通过最近邻插值算法,得到一个 4×4 的灰度图。
Python OpenCV 图像的几何变换,先说不平凡的 resize 函数
先通过坐标系去了解像素在缩放的时候的变化。
Python OpenCV 图像的几何变换,先说不平凡的 resize 函数
上图中最后可以到的结论是:

  • 目标像素的 x 值 = 原像素的 x 值 * 倍数;
  • 目标像素的 y 值 = 原像素的 y 值 * 倍数;

本案例的倍数是多少呢?很容易计算,原来的图像是 3×3,现在是 4×4,那倍数在 x,y 上都是 4/3 = 0.75

先看一下运算之后得到的结果如下所示:
Python OpenCV 图像的几何变换,先说不平凡的 resize 函数
这里列举两个点的像素值计算,拿目标图像 4x4灰度图 中的 (3,0)(3,3) 两个点进行说明。

  • (3x0) 点的值等于 (3 x 0.75 ≈ 2,0 x 0.75 = 0),原图像 (2,0) 点的颜色为 222
  • (3x3) 点的值等于 (3 x 0.75 ≈ 2,3 x 0.75 ≈ 2),原图像 (2,2) 点的颜色为 45

掌握了原理之后,就可以自己实现这个算法了,首先看一下 OpenCV 内置的函数实现结果。

import cv2 as cv
import numpy as np

# 最近邻插值算法,来源梦想橡皮擦 https://dream.blog.csdn.net/
def nearest_demo(src, multiple_x, multiple_y):
    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) 坐标在旧图中是哪个值
            old_y = round(y/multiple_y)
            old_x = round(x/multiple_x)
            tar_img[y, x] = src[old_y, old_x]

    return tar_img

src = cv.imread("./t2.jpeg")
print(src.shape)
cv.imshow("src", src)
# dsize = (cols,rows) 中文,(宽度,高度)
dst = cv.resize(src, (0, 0), fx=2, fy=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()

运行之后发现确实官方的算法更优一些。
Python OpenCV 图像的几何变换,先说不平凡的 resize 函数

橡皮擦的小节

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

相关阅读


技术专栏

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

今天是持续写作的第 83 / 100 天。
如果你想跟博主建立亲密关系,可以关注同名公众号 梦想橡皮擦,近距离接触一个逗趣的互联网高级网虫。
博主 ID:梦想橡皮擦,希望大家点赞评论收藏

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/125824.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 如何设置电信光猫?图解手把手教你(超级详细)「建议收藏」

    如何设置电信光猫?图解手把手教你(超级详细)「建议收藏」自从电信升级成光纤之后,光猫经常有点小问题的,如果电信说帮你设置好漫天要价的话,求人还不如求自己,或者电信送的光猫坏了,买他们的超贵,自己买一个又好又便宜的自己设置就的了注意:2016年以后,电信为

  • 成熟的男人喜欢什么样的女性?

    成熟的男人喜欢什么样的女性?很多人以为男人不管是18还是88,都喜欢18的女孩子。其实错了,准确来说是片面了。就我自己和身边朋友的观察,大多数真正成熟的男性,更喜欢的是性格的契合,而不单是你的身高、三围、和精致的脸。具体说说吧,但仅代表我自己。1、能独立自主的女性最有吸引力。男人的征服欲仿佛是带在基因里的,特别是成熟的男人。傻白甜人设,在成熟男人那里,真的不太有优势。他们更喜欢的是“势均力敌”的较量,而不是给小迷妹当人生启蒙老师。事业独立、生活独立的女性,更受男人的欢迎。大多数成年人的世界里,感情与性,是生活的调味品,而不是必需品

  • R语言绘制火山图_r语言画曲线图

    R语言绘制火山图_r语言画曲线图基因表达差异火山图提到差异火山图,相信很多同学肯定不陌生。因为形似火山(喷发),所以称为火山图。差异火山图最常见于转录组数据的分析中,在基因表达层面,用于展示两组间表达量上调和下调的基因。常规的火山图中主要包含了两个重要信息,差异表达倍数(FoldChange值,简称FC,作图时会对FC进行log转化,根据logFC值的正负判断这些基因的表达量是上调了还是下调了)以及统计学显著性p值(p-value,通常是FDR校正后的p值,根据校正后p值判断基因表达量上调或下调是否具有显著性)。因此在判..

    2022年10月19日
  • apache日志格式定义及示例说明[通俗易懂]

    apache日志格式定义及示例说明[通俗易懂]来源:https://blog.csdn.net/newhappy2008/article/details/7604956有时候我们需要定制Apache默认日志的格式和内容,比如增加或减少日志所记录的信息、改变默认日志文件的格式等。本文介绍可以用日志记录的所有信息,以及如何设置Apache使其记录这些信息。一、Apache日志格式定义  很久以前,日志文件只有一种格式,这就是“公共…

  • 推荐系统(Recommendation system )介绍[通俗易懂]

    推荐系统(Recommendation system )介绍[通俗易懂]前言随着电子商务的发展,网络购物成为一种趋势,当你打开某个购物网站比如淘宝、京东的时候,会看到很多给你推荐的产品,你是否觉得这些推荐的产品都是你似曾相识或者正好需要的呢。这个就是现在电子商务里面的推

  • acwing吧_并查集时间复杂度

    acwing吧_并查集时间复杂度小 A 和小 B 在玩一个游戏。首先,小 A 写了一个由 0 和 1 组成的序列 S,长度为 N。然后,小 B 向小 A 提出了 M 个问题。在每个问题中,小 B 指定两个数 l 和 r,小 A 回答 S[l∼r] 中有奇数个 1 还是偶数个 1。机智的小 B 发现小 A 有可能在撒谎。例如,小 A 曾经回答过 S[1∼3] 中有奇数个 1,S[4∼6] 中有偶数个 1,现在又回答 S[1∼6] 中有偶数个 1,显然这是自相矛盾的。请你帮助小 B 检查这 M 个答案,并指出在至少多少个回答之后可

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号