python-opencv Tutorials 一码人翻译(7)核心操作 基本的图片操作

  • 目标

学习:

访问像素值并修改它们

访问图像属性

设定兴趣区域(ROI)

分裂和合并图片

本节几乎所有的操作都与Numpy而不是OpenCV有关。对Numpy有很好的了解,需要使用OpenCV编写更好的优化代码。

(示例将在Python终端中显示,因为它们中的大多数都只是单行代码)

访问和修改像素值

让我们先加载一个颜色图像:

import numpy as np
import cv2 as cv

img = cv.imread('lenna.jpg')

 你可以通过它的行和列坐标来访问一个像素值。对于BGR图像,它返回一个蓝色、绿色、红色值的数组。

px = img[100,100]
print(px)

 结果

[ 73  95 177]

对于灰度图像,只返回相应的强度。 

blue = img[100,100,0]
print( blue )

结果 

73

Numpy是一个用于快速数组计算的优化库。因此,简单地访问每个像素值并修改它将会非常缓慢,而且会被阻止。

请注意

上面的方法通常用于选择一个数组的区域,比如前5行和最后3列。对于单个像素访问,Numpy数组方法、array.item()和array.itemset()被认为是更好的,但是它们总是返回一个标量。如果你想要访问所有的B、G、R值,你需要分别调用array.item()。

更好的像素访问和编辑方法:

# accessing RED value
>>> img.item(10,10,2)
59

# modifying RED value
>>> img.itemset((10,10,2),100)
>>> img.item(10,10,2)
100
  • 访问图像属性

图像属性包括行数、列和通道数、图像数据类型、像素数等。

图像的形状是由img形状来访问的。它返回一组行、列和通道的元组(如果图像是颜色):

print( img.shape )
(450, 210, 3)

请注意

如果一个图像是灰度级的,那么返回的元组只包含行和列的数量,所以这是一个很好的方法来检查加载的图像是灰度还是彩色。

print( img.size )
283500

 图像数据类型是通过“img.dtype”获得的:

print( img.dtype )
uint8

opencv python代码中的大量错误是由无效的数据类型引起的。

  • 图像ROI

有时,你必须要玩特定的图像区域。为了在图像中进行眼睛检测,首先在图像上进行第一次人脸检测。当获得一张人脸时,我们只选择脸部区域,并在里面搜索眼睛,而不是搜索整个图像。它提高了准确性(因为眼睛总是盯着脸:D)和性能(因为我们在一个小区域内搜索)。

使用Numpy索引再次获得ROI。在这里,我选择了脸并将其复制到图像中的另一个区域:

import numpy as np
import cv2 as cv

img = cv.imread('lenna.jpg')
ball = img[35:80, 90:120]
img[5:50, 10:40] = ball
cv.imshow('res', img)
cv.waitKey(0)
cv.destroyAllWindows()

 

分割和合并图像通道

有时你需要在B、G、R的图像通道上分开工作。在这种情况下,您需要将BGR图像分割成单个通道。在其他情况下,您可能需要将这些单独的通道连接到BGR映像。你可以简单地通过:

b,g,r = cv.split(img)
img = cv.merge((b,g,r))
b,g,r = cv.split(img)
img = cv.merge((b,g,r))

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

或者

b = img[:,:,0]

 假设您想将所有的红色像素设置为0,您不需要首先分割通道。Numpy索引更快:

img[:,:,2] = 0

split()是一个代价高昂的操作(就时间而言)。所以只有在你需要的时候才去做。否则就会使用Numpy索引。

  • 为图像(填充)创建边框

如果你想在图像周围创建一个边框,比如一个相框,你可以使用cv.copyMakeBorder()。但是它有更多的关于卷积运算,零填充等的应用,这个函数需要以下参数:

src -输入图像

top, bottom, left, right-边界宽度在相应方向上的像素数量

borderType-标记要添加什么类型的边框。它可以是以下类型:

cv.BORDER_CONSTANT-增加一个恒定的颜色边界。该值应该作为下一个参数给出。

cv.BORDER_REFLECT-边界将是边界元素的镜像反射,像这样:fedcba|abcdefgh|hgfedcb

cv.BORDER_REFLECT_101 or cv.BORDER_DEFAULT—和上面一样,但是有一点变化,像这样:gfedcb|abcdefgh|gfedcba

cv.BORDER_REPLICATE——最后一个元素在整个过程中被复制,像这样:aaaaaa|abcdefgh|hhhhhhh

cv.BORDER_WRAP无法解释,它会是这样的:cdefgh|abcdefgh|abcdefg

value -边界类型为cv.BORDER_CONSTANT

 

下面是一个示例代码,演示了所有这些边界类型,以便更好地理解:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

BLUE = [255,0,0]

img1 = cv.imread('python.jpg')

replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101)
wrap = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_WRAP)
constant= cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_CONSTANT,value=BLUE)

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()

猜你喜欢

转载自blog.csdn.net/qq_41905045/article/details/81295931