二、OpenCV-python 之 图像像素操作

1、像素值操作

OpenCV读取图像后,将其作为numpy存储,所以大部分的图像计算都是numpy的工作

px = img[100,100]				# 获取像素点(100,100)的三通道颜色值
blue = img[100,100,0]			# 获取像素点(100,100)的蓝色通道数值
img[100,100] = [255,255,255]	# 修改像素点(100,100)的三通道颜色值

img.item(10,10,2)				# 获取像素值的高效方式
img.itemset((10,10,2),100)		# 修改像素值的高效方式

# 图像属性
img.shape						# 返回一个tuple,图像的shape(行,列,通道)
img.size						# 返回图像的像素数量,其实就是上面tuple的乘积
img.dtype						# 返回图像像素值的类型,注意不是图像类型

# 感兴趣区域ROI
ball = img[280:340, 330:390]	# 用numpy剪裁图像
img[273:333, 100:160] = ball	# 指定区域赋值

# 图像通道
b,g,r = cv.split(img)			# 图像通道分割,开销很大,尽量不要直接用,可以的话用numpy代替
img = cv.merge((b,g,r))			# 通道合并

# 复制图像:将图像复制到另一目标图像的中心
cv.copyMakeBorder(
    src,				# 源图像
    dst,				# 目标图像
    top,
    bottom, 
    left, 
    right,				# 目标图像的上下左右不同方向上边界的宽度,单位为 px
    borderType,			# 边界填充方式
    value				# 边界填充值(如果填充方式是BORDER_CONSTANT)
)

2、图像算术运算

# 图像混合,OpenCV中的加法是一个饱和操作,到达峰值255后就处于峰值不变(numpy中超过峰值后会对峰值取余)
cv.add(src1, src2, dst, mask, dtype)
# 加入权重后的图像混合,dst=α⋅img1+β⋅img2+γ,
cv.addWeighted(src1, alpha, src2, beta, gamma, dst, dtype)

这里给出一个图像位操作的实例,目标是将一张图像的一个logo抠出来,放到另一张图像中(指定像素位置的替换操作)。不能直接用加法,因为会改变像素的值;也不能用混合,会产生透明度。
像素级别的替换操作的思路是:先得到ROI-logo的掩码,然后抠出logo,将目标位置掏空,然后做加法操作。

# Load two images
img1 = cv.imread('target.jpg')
img2 = cv.imread('logo.png')

# I want to put logo on top-left corner, So I create a ROI
rows, cols, channels = img2.shape
roi = img1[0:rows, 0:cols]

# Now create a mask of logo and create its inverse mask also
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)       # 置为二值图,大于阈值置为255(白),用于得到logo(非logo位置全为0)
mask_inv = cv.bitwise_not(mask)                                     # mask反转,与logo对应的位置为0(给logo留出位置)

# Now black-out the area of logo in ROI
img1_bg = cv.bitwise_and(roi, roi, mask = mask_inv)                 # 目标图像中与logo对应的位置腾出来
# Take only region of logo from logo image.
img2_fg = cv.bitwise_and(img2, img2, mask = mask)                   # 像素与操作,根据mask抠出logo

# Put logo in ROI and modify the main image
dst = cv.add(img1_bg,img2_fg)                                       # 相加,注意这里 ROI 的logo位置已经被掏空了(均为0),直接相加不会改变logo像素值
img1[0:rows, 0:cols ] = dst                                         # 合并到目标图像

cv.imshow('res',img1)
cv.waitKey(0)
cv.destroyAllWindows()

cv.bitwise_and(img1, img2,mask)
像素与操作,三个参数的尺寸是一样的,mask中为0的位置在输出图像中也为0,非0位置在输出图像中的像素值是img1、img2对应位置像素的与操作(这其实就是抠图)。

最终的效果如下(左边是logo掩码):

在这里插入图片描述

3、处理性能与优化

OpenCV中对图像处理、像素计算等做了很多优化(例如SSE2、AVX等),优化开启与否直接影响到程序执行的性能;它也提供了一些监测模块(例如time)来帮助观测代码的性能。

time 模块:可以给出代码执行所耗时间;
profile 模块:可以给出代码执行的详细报告,例如函数占用的时间、调用次数等。

# 时间监测
e1 = cv.getTickCount()						# 返回在一个引用事件(例如程序开始运行的时刻)之后到调用此函数的时刻的时钟周期数,其实就是这个时候的时间点
### your code execution ###
e2 = cv.getTickCount()
time = (e2 - e1)/ cv.getTickFrequency()		# cv.getTickFrequency()返回时钟周期的频率,或每秒时钟周期的数量。

# 优化处理
cv.useOptimized()							# 查看是否开启优化
cv.setUseOptimized(False)					# 设置是否开启优化,True为启动,False为关闭

通常情况下,OpenCV的处理速度比numpy快得多,所以相同的操作尽量用OpenCV来实现(当然,这也并不是绝对的)。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值