opencv与numpy的图像基本操作
作者:邹成卓 发布时间:2022-06-20 12:20:10
1. 像素基本操作
1.1 读取、修改像素
可以通过[行,列]坐标来访问像素点数据,对于多通道数据,返回一个数组,包含所有通道的值,对于单通道数据(如gray),返回指定坐标的值,也可以通过 [行,列,通道index] 来访问某坐标某通道的值。
>>> import cv2
>>> import numpy as np
>>> img = cv2.imread('messi5.jpg')
>>> px = img[100,100]
>>> print( px )
[157 166 200]
# accessing only blue pixel
>>> blue = img[100,100,0]
>>> print( blue )
157
可以直接通过坐标修改像素值
>>> img[100,100] = [255,255,255]
>>> print( img[100,100] )
[255 255 255]
然而直接像上面这样去读取、修改每个像素的值,效率是比较低的,可以使用下面的方法,效率是更高的
# accessing RED value
>>> img.item(10,10,2)
59
# modifying RED value
>>> img.itemset((10,10,2),100)
>>> img.item(10,10,2)
100
1.2 读取图像属性
读取图像尺寸,返回一个元组 (行,列,通道数)
>>> print( img.shape )
(342, 548, 3)
读取像素大小, 行 列 通道数
>>> print( img.size )
562248
像素数据类型
>>> print( img.dtype )
uint8
1.3 图像ROI操作
可以直接编辑像素区域,例如把图像左下角50*50的像素复制到左上角
import cv2
import numpy as np
img = cv2.imread("test.jpg")
print(img.shape)
roiTest = img[475:525, 0:50]
img[0:50, 0:50] = roiTest
cv2.imshow("image",img)
cv2.waitKey(0)
1.4 分割、合并通道
有些情况下需要对图像的某一通道数据进行操作,此时会用到分割、合并通道数据
>>> b,g,r = cv2.split(img)
>>> img = cv2.merge((b,g,r))
或者
b = img[:,:,0]
假设想编辑红色通道的数据,全部设置为0,不需要这样分割后编辑, img[:,:,2] = 0
这样即可。cv2.split操作是一个很耗时的操作,可以用numpy索引替代的操作,尽量用numpy索引来做。
1.4 生成图像边框
使用 cv2.copyMakeBorder
函数可添加图像边框,支持多种边框算法
void cv::copyMakeBorder (
InputArray src, //原图
//目标图(cpp版本中,若传入此数据且选BORDER_TRANSPARENT,则此数据被top/bottom/left/right切出来的roi部分不会被做任何修改,此图像大小=dst.rows+top+bottom,dst.cols+left+right)
OutputArray dst,
int top, //top/left/bottom/right 四个方向上的边框像素
int bottom,
int left,
int right,
int borderType, //边框类型见下图
const Scalar & value = Scalar() //边框类型为BORDER_CONSTANT时的边框像素
)
BLUE = [255, 0, 0]
img1 = cv2.imread("test.jpg")
replicate = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_CONSTANT, value=BLUE)
print(img1.shape, reflect.shape)
plt.subplot(231), plt.imshow(img1, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
plt.show()
上面的例子可以比较直观的看到各种border的效果,同时也能发现,python版的api与cpp版本的相比,默认初始化了一块原始图尺寸+各方向边框尺寸的图像内存,作为内置的dst参数。
输出尺寸:(525, 700, 3) (725, 900, 3)
2. 图像的基本算术操作
2.1 图像相加
图像相加,两个图像应该有相同的shape,或者图像和一个标量相加,或者图像和一个与其通道数相同的一维数组相加。
opencv的相加与numpy相加时,在超出数据类型范围时的处理不同
>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> print( cv2.add(x,y) ) # 250+10 = 260 => 255
[[255]]
>>> print( x+y ) # 250+10 = 260 % 256 = 4
[4]
cpp版本的api还支持mask等参数
void cv::add (
InputArray src1,
InputArray src2,
OutputArray dst,
InputArray mask = noArray(),
int dtype = -1
)
2.2 图像混合
opencv通过 cv::addWeighted
函数提供了将两个图像混合在一起的方法
dst=α⋅img1+β⋅img2+γ
img1 = cv2.imread('ml.png')
img2 = cv2.imread('opencv-logo.png')
dst = cv2.addWeighted(img1,0.7,img2,0.3,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
通过cv2.seamlessClone函数还能做更精细的图像局部融合。
来源:https://www.zoucz.com/blog/2019/03/07/50ef43b0-40a5-11e9-9947-3d7b79f522a2/
猜你喜欢
- Python的数据结构有列表、元组、集合、字典等,可以吧列表当成一个清单,是有序的,我们可以通过索引访问到列表中的元素,列表还可以进行修改、
- 第1题:Python里面如何实现tuple和list的转换?函数tuple(seq)可以把所有可迭代的(iterable)序列转换成一个tu
- 一、设计说明设计这个自动化的目的是想要交替、重复地使用固定的几个分区(分区编号01~05)来保存数据,当最后一个分区就是快满的时候,我们会把
- 在python中经常会用到pandas来处理数据,最常用的数据类型是dataframe,但是有时候在dataframe有时间字段需要画时间序
- 注意:我用的python2.7,大家如果用Python3.0以上的版本,请记得在print()函数哦!如果因为版本问题评论的,不做回复哦!!
- Python中使用threading.Condition交替打印两个字符的程序。这个程序涉及到两个线程的的协调问题,两个线程为了能够相互协调
- 前言老早就看到新闻员工通过人脸识别监控老板来摸鱼。有时候摸鱼太入迷了,经常在上班时间玩其他的东西被老板看到。自从在咸鱼上淘了一个树莓派3b,
- 本文实例为大家分享了python使用sendmail发送邮件的具体代码,供大家参考,具体内容如下参考链接:How do I send mai
- 举个例子来说,要查找出2007-10-12至2007-10-31之间在网站上注册的会员,选择好日期后,点击“查询”按钮,发现2007-10-
- 语言的内存管理是语言设计的一个重要方面。它是决定语言性能的重要因素。无论是C语言的手工管理,还是Java的垃圾回收,都成为语言最重要的特征。
- 要使用多个定界符拆分字符串:使用 re.split() 方法,例如 re.split(r',|-', my_str)。re.
- 本文为大家分享了python字典DICT类型合并的方法,供大家参考,具体内容如下我要的字典的键值有些是数据库中表的字段名, 但是有些却不是,
- 在缺失值填补上如果用前后的均值填补中间的均值,比如,0,空,1,我们希望中间填充0.5;或者0,空,空,1,我们希望中间填充0.33,0.6
- 这篇文章主要介绍了如何给Python代码进行加密,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以
- 很多人对于CSS都是边干边学习,因为它不像C#之类的语言那么复杂,看起来似乎挺简单,然而正是这种对CSS的不完整的理解,导致了许多的CSS代
- 我们在编写asp程序时经常会使用到这个功能,一般我们这样判断如:if a="" then ,而这个函数考虑的就比较全面了
- 本文实例讲述了Python实现的多线程http压力测试代码。分享给大家供大家参考,具体如下:# Python version 3.3__au
- 我们用Select的onchange事件时,常会遇到这样一个问题,那就是连续选相同一项时,不触发onchange事件.select的onch
- 在使用出colab进行模型训练时,发现colab的python版本更新为了3.7.11,而我的代码要在python3.6下才行配置好环境,于
- 要达到二级名的效果,必须一下条件以及流程:1、必须有一个顶级域名,而且此域名必须做好泛解析并做好指向。2、必须有一台属于你的独立的服务器。泛