Python语言OpenCV开发之OpenCV的核心操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Eric_lmy/article/details/80962659

前言

从概念上讲,一个字节能表示0到255的整数。目前,对于所有的实施图像应用而言,虽然有其他的便是形式,但一个像素通常有每个通道的一个字节表示。一个OpenCV图像是.array类型的二维或三维数组。8位的灰度图像是一个含有字节值的二维数组。一个24位的BGR图像是一个三维数组,它也包含了字节值。即可以使用表达式进行访问这些值。
本章讲述两个内容,一是图像的基础操作,而是图像上的算术运算

正文

1、图像的基础操作
1.1、 获取并修改图像的像素值
读入(cv2.imread())一幅图像,可以根据像素的行和列的坐标获取它的像素值。对于BGR图像而言,返回的值为B,G,R的值,对于灰度图而言,会返回它的灰度值。
例如:

img = cv2.imread('./image/test2.jpg')
px = img[100,100]
print(px)# [40  35  34]
blue = img[100,100,0]
print(blue)# 40
img[100,100] = [255,255,255]
print(img[100,100])# [255,255,255]

numpy是经过优化了的进行快速矩阵运算的软件。所以不推荐逐个取像素值并修改。比如前5行的后3列,对于获取每一个像素值,也许使用Numpy的array.item()和array.itemset()会更好。但是返回值是标量。如果想获得所有的B,G,R的值需要使用array.item()分割他们。例如:

print(img.item(10,10,2))# 33
img.itemset((10,10,2),100)
print(img.item(10,10,2))# 100

1.2、 获取图像的属性
图像的属性包括:行,列,通道,图像数据类型,像素数目等。img.shape可以获取图像的形状,返回值是一个包含行数,列数,通道数的元祖。如果图像是灰度图,返回值仅有行数和列数。所以通过检查这个返回值就可以知道加载的是灰度图还是彩色图。例如:

print(img.shape) # (375, 500, 3)
#img.size 可以返回图像的像素数目
print(img.size)# 562500 (375*500*3)
#img.dtype返回的是图像的数据类型。
print(img.dtype)# uint8

注意:在debug时img.dtype非常重要。因为在OpenCV-Python代码中经常出现数据类型不一致。

1.3、图像ROI(感兴趣区域)
ROI也是使用Numpy索引来获得的,将选择中的部分拷贝到图像的其他区域。
例如:

ball = img[280:340, 330:390]
img[273:333, 100:160]=bal

看一下效果(多了一个球)
enter image description here

1.4、 拆分以及合并图像通道
有时候需要对BGR三个通道分别进行操作。就需要把BGR拆分成单个通道。有时需要把独立通道的图片并成一个BGR图像,例如:

b,g,r = cv2.split(img)
img = cv2.merge(b,g,r)
# 或者
img1 = img[:,:,0]

假如想所有像素的红色通道值都为0,不必先拆分再赋值,可以使用Numpy索引,这会更快。例如:

img[:,:,2] = 0

注意:cv2.split()是一个比较耗时的操作。只有真正需要时才用它。如果上面的这些数组的操作觉得看不懂的话,那么建议你去看看了解一下python中数组的切片操作。
1.5、为图像扩边(填充)
这个操作就像是给图像加了一个相框的操作,只是这个相框的内容有不同的选择,也就是在图像的周围创建一个边,可以使用cv2.copyMakeBorder()函数。这经常在卷积运算或0填充时被用到。具体参数如下:
1. src:输入图像
2. top、bottom、left、right对应边界的像素数目
3. borderType要添加哪种类型的边界,类型如下:
a) cv2.BORDER_CONSTANT添加有颜色的常数值边界(需要下一个参数)
b) cv2.BORDER_REFLECT边界元素的镜像
c) cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT类似上面的
d) cv2.BORDER_REPLICATE重复最后一个元素。
e) cv2.BORDER_WRAP
4. value边界元素(类型是BORDER_CONSTANT时)
**注意:**OpenCV中按BGR排列,matplotlib中是按RGB排列;所以在显示图像是,要进行转换的。这个点已经提过很多次了。
效果大概如下:
enter image description here
2、 图像上的算术运算
2.1 图像加法
图像加法就是把图像相同位置上的像素值进行加法操作,在OpenCV里使用函数cv2.add()将两幅图像进行加法运算,当然也可以直接使用numpy,例如:res=img1+img2。两幅图像的大小、类型必须一致,或者第二图像可以是一个简单的标量值。但有一点要注意的,OpenCV中的加法与Numpy的加法是有所不同的,OpenCV的加法是一种饱和操作,而Numpy的加法是一种模操作:例如:

x = np.uint8([250])
y = np.uint8([10])
print(cv2.add(x,y))# 250+10 = 260 => 255
print(x+y)# 250+10 = 260%256 =4

这种差别在你对两幅图像进行加法时会更加明显。Opencv的结果会更好一点。
下面看一下效果:
enter image description here
2.2 图像的混合
这其实也是加法,和上面不同的是用户可以选择两幅图像的权重进行相加,这种操作会会呈现一种透明的感觉,图像混合的计算公式如下:
G(x) = (1-a)F(x) + aH(x)
a的取值范围是(0,1),通过修改可以实现不同的效果,使用的函数是cv2.addWeighted();

扫描二维码关注公众号,回复: 5830629 查看本文章
import cv2
img1 = cv2.imread('dog.jpg')
img2 = cv2.imread('shu.jpg')
# img3 = cv2.add(img1, img2)
img3 = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
while True:
    if cv2.waitKey(20)&0xff == 27:
        break
cv2.destroyAllWindows()

效果如下:
enter image description here

2.3 按位运算
按位操作有:AND,OR,NOT,XOR等。当提取图像的一部分,选择非矩形ROI时这些操作会很有用。函数为相关的操作加“cv2.bitwise_”前缀。如:cv2.bitwise_not。对于2元操作而言,至少两个参数,src1,src2;dst参数返回结果可选,mask参数也是可选,指定mask区域进行相关操作。

import numpy as np
import cv2
# Load two images
img1 = cv2.imread('./image/test2.jpg')
img2 = cv2.imread('./image/logo.jpg')
# 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 ] # 感兴趣的大小和logo图片大小一致
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)# 不同颜色空间的转换,下一节会详细讲解
ret, mask = cv2.threshold(img2gray, 200,255,v2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)
# Now black-out the area of logo in ROI
img1_bg = cv2.bitwise_and(roi,roi,mask = mask)
cv2.imshow('bg',img1_bg)
# Take only region of logo from logo image.
img2_fg = cv2.bitwise_and(img2,img2,mask = mask_inv)
cv2.imshow('fg',img2_fg)
# Put logo in ROI and modify the main image
dst = cv2.add(img1_bg,img2_fg)
img1[0:rows, 0:cols ] = dst
cv2.imshow('result',img1)
cv2.waitKey(0)
cv2.destroyAllWindows()

显示效果如下:
enter image description here

小结
通过本章内容,应该能对图像有个充分的了解了,并能去获取修改运算图像的操作了。下一章内容会讲到一些图像的变换的操作。
本章内容不是太多,如有差错请指出,谢谢!

猜你喜欢

转载自blog.csdn.net/Eric_lmy/article/details/80962659
今日推荐