OpenCV-Python图像处理教程:图像基本操作

目录

    • 目录
    • 访问和修改像素值
    • 访问图片属性
    • 图像ROI(Region of Interest)
    • 图像通道的分割和合并
    • 为图像制作边框(Padding)

本节中几乎所有的操作都与Numpy相关,而不是OpenCV。 需要熟悉Numpy才能使用OpenCV编写更好的优化代码。

    注:本文翻译自openCV官网教程,为方便理解,有些许添加或者改动
    [英文版链接]
    https://docs.opencv.org/trunk/d3/df2/tutorial_py_basic_ops.html

访问和修改像素值

首先,读取彩色图片

import numpy as np
import cv2 as cv
img = cv.imread('xxx.jpg')

您可以通过其行和列坐标访问像素值。 对于BGR图像,它返回一个蓝色,绿色,红色值的数组。 对于灰度图像,只返回相应的亮度。

px = img[100,100] #取坐标值为(100,100)的像素点
print(px)#输出一个数组,比如[157,166,200]
#只访问蓝色像素,绿色像素,红色像素
blue = img[100,100,0] #157
green= img[100,100,1] #166
red= img[100,100,2] #200

同样,可以修改像素值

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

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

#访问红色通道值,0蓝 1绿 2红
img.item(10,10,2) #59
#修改红色通道值
img.itemset((10,10,2),100)
img.item(10,10,2) #100

访问图片属性

图片的属性包括行数,列数,通道数,图片数据类型,像素数等

print(img.shape) #(342,548,3)
#通过img.shape来获取img的形状,返回一个元组(tuple),
#分别为行数,列数和通道数(如果是彩色图片就返回第三个参数)

注:如果是灰度图,则返回的元组仅包含行数和列数,因此检查加载的图像是灰度还是颜色是一种好方法。

print(img.size)#返回总的像素数目 = 行数*列数(*通道数)
print(img.dtype)#返回图片的数据类型 如:unit8,float32,float64等

注:调试时img.dtype非常重要,因为OpenCV-Python代码中的大量错误是由无效的数据类型引起的。

图像ROI(Region of Interest)

有时候,检测图像时,需要选取一定的图像区域。 比如,对于图像中的眼睛检测,首先在整个图像上进行人脸检测。 当获得脸部时,我们单独选择脸部区域并在其内部搜索眼睛而不是搜索整个图像。 它提高了准确性(因为眼睛总是在脸上)和性能(因为我们在一个小区域搜索)
ROI也是使用Numpy索引获得,在下面的例子中,我选择球,并将其复制到图像中的另一个区域:

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

效果如图所示:
OpenCV-Python图像处理教程:图像基本操作_第1张图片

图像通道的分割和合并

有时您需要分别处理B,G,R图像通道。 在这种情况下,您需要将BGR图像拆分为单个通道。 在其他情况下,您可能需要将这些单个频道加入BGR图像。 你可以简单地通过:

b,g,r = cv.split(img)
img=cv.merge(b,g,r)
#或者
b = img[:,:,0]
#假设您要将所有红色像素设置为零,则不需要先分割通道。 Numpy索引速度更快:
img[:,:,2]=0
    温馨提示:cv.split()是一个代价高昂的操作(就时间而言)。 所以只有在你需要的时候才能做到。
    否则,推荐使用Numpy索引。

为图像制作边框(Padding)

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

  • src-输入图像
  • top,bottom,left,right-(上,下,左,右)相应方向上的边框宽度值
  • borderType-标识定义要添加的边界类型。 它可以是以下类型:
    - cv.BORDER_CONSTANT-添加一个常量彩色边框。 下一个参数指明颜色值。
    - cv.BORDER_REFLECT-边框将镜像反射边框元素,例如:fedcba | abcdefgh | hgfedcb
    - cv.BORDER_REFLECT_101 或者 cv.BORDER_DEFAULT-跟上种方法差不多,只是有稍微的变化,例如:gfedcb|abcdefgh|gfedcba
    - cv.REPLICATE-最后一个元素被复制到整个,例如:aaaaaa|abcdefgh|hhhhhhh
    - cv.BORDER_WARP-无法解释,举个栗子:cdefgh|abcdefgh|abcdefg
  • value-当边框类型为cv.BORDER_CONSTANT时,则为边框颜色

以下是展示所有这些边界类型以便更好理解的示例代码:

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

BULE=[255,0,0]
img1 = cv.imread('XXX.png')

replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT)
reflect_101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101)
wrap = cv.coprMakeBorder(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()

看到下面的结果。 (图像与matplotlib一起显示,所以红色和蓝色通道将互换:
OpenCV-Python图像处理教程:图像基本操作_第2张图片换):

你可能感兴趣的:(数字图像处理,python,openCV)