基于opencv4.1官方文档学习记录,并添加个人学习记录笔记

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

image = cv.imread('girl.jpg', 1)

# 访问一个像素点
px = image[100, 100]
print(px)

# 访问像素的一个通道
# ;前两个为位置,后一个为通道号
blue = image[100, 100, 0]
green = image[100, 100, 1]
red = image[100, 100, 2]
print(blue, green, red)

# 灰度图像相似,只不过返回的不在是数组 而是一个灰度值


# 修改像素值
px = [255, 255, 255]
print(px)
image[100, 100] = [20, 80, 160]
print(image[100, 100])

# Numpy是用于快速数组计算的优化库。
# 因此,简单地访问每个像素值并对其进行修改将非常缓慢,因此不建议使用。

# 注意 上面的方法通常用于选择数组的区域,例如前5行和后3列。
# 对于单个像素访问,Numpy数组方法array.item()和array.itemset())被认为更好,
# 但是它们始终返回标量。如果要访问所有B,G,R值,则需要分别调用所有的array.item()。
print(image.item(100, 100, 0), image.item(100, 100, 1), image.item(100, 100, 2))

image.itemset((100, 100, 0), 60)
image.itemset((100, 100, 1), 35)
image.itemset((100, 100, 2), 47)

print(image.item(100, 100, 0), image.item(100, 100, 1), image.item(100, 100, 2))

# 图像属性包括行数,列数和通道数,图像数据类型,像素数等。
# 图像的形状可通过img.shape访问。它返回行,列和通道数的元组(如果图像是彩色的):
print(image.shape)
# 注意 如果图像是灰度的,则返回的元组仅包含行数和列数,因此这是检查加载的图像是灰度还是彩色的好方法

# 像素总数可通过访问img.size
print(image.size)
# 图像数据类型通过img.dtype获得
print(image.dtype)

# 有时候,不得不处理一些特定区域的图像。
# 对于图像中的眼睛检测,首先对整个图像进行人脸检测。
# 在获取人脸图像时,我们只选择人脸区域,搜索其中的眼睛,而不是搜索整个图像。
# 它提高了准确性(因为眼睛总是在面部上:D )和性能(因为我们搜索的区域很小)。
# 使用Numpy索引再次获得ROI。在这里,我要选择球并将其复制到图像中的另一个区域:

image1 = image.copy()
Roi = image1[250:320, 330:380]
image1[80:150, 60:110] = Roi
cv.imshow('image1', image)
cv.imshow('image2', image1)
cv.waitKey(0)
cv.destroyAllWindows()

# 有时需要分别处理图像的B,G,R通道。
# 在这种情况下,你需要将BGR图像拆分为单个通道。
# 在其他情况下,你可能需要将这些单独的频道加入BGR图片。
# 可以通过以下方式简单地做到这一点

b, g, r = cv.split(image)
image = cv.merge((b, g, r))
# 或者
b = image[:, :, 0]

# 所以也有单独操作一个通道
image[100, 100, 0] = 0

# cv.split()是一项耗时的操作(就时间而言)。
# 因此,仅在必要时才这样做。否则请进行Numpy索引。


# 为图像设置边框(填充)
#
# 如果要在图像周围创建边框(如相框),则可以使用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.BORDER_REPLICATE最后一个元素被复制,像这样: aaaaaa | abcdefgh | hhhhhhh
#
#     cv.BORDER_WRAP难以解释,它看起来像这样: cdefgh | abcdefgh | abcdefg
#
#     value -边框的颜色,如果边框类型为cv.BORDER_CONSTANT

BLUE = [255, 0, 0]
img1 = cv.imread('gugu.jpg')

# 图像与matplotlib一起显示。因此红色和蓝色通道将互换
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()


# 图像加法
# 可以通过OpenCV函数cv.add()或仅通过numpy操作res = img1 + img2添加两个图像。
# 两个图像应具有相同的深度和类型,或者第二个图像可以只是一个标量值。
# 注意 OpenCV加法和Numpy加法之间有区别。OpenCV加法是饱和运算,而Numpy加法是模运算。
x = np.uint8([250])
y = np.uint8([10])
print(cv.add(x, y))  # 250+10 = 260 => 255
print(x+y)           # 250+10 = 260 % 256 = 4
# 当添加两个图像时,它将更加可见。OpenCV功能将提供更好的结果。
# 因此,始终最好坚持使用OpenCV功能。


# 两张图像按比例融合
img1 = cv.imread('girl.jpg')
img1 = img1[300:600, 300:800]
img2 = cv.imread('gugu.jpg')
img2 = img2[0:300, 0:500]
# cv.addWeighted()  参数 图像一 图像一权重 图像二 图像二权重 整体偏移量
dst = cv.addWeighted(img1, 0.7, img2, 0.3, 0)
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()

# 按位运算
#
# 这包括按位 AND、 OR、NOT 和 XOR 操作。
# 它们在提取图像的任何部分(我们将在后面的章节中看到)、定义和处理非矩形 ROI 等方面非常有用。
# 下面我们将看到一个例子,如何改变一个图像的特定区域。
# 我想把 bird 的标志放在一个图像上面。
# 如果我添加两个图像,它会改变颜色。如果我混合它,我得到一个透明的效果。
# 但我希望它是不透明的。如果是一个矩形区域,我可以使用 ROI,就像我在中所做的那样。
# 但是 bird 不是长方形的。所以可以使用如下的按位操作来实现:

# 加载两张图片
img1 = cv.imread("girl.jpg")
img2 = cv.imread('bird.png')
# 我想把logo放在左上角,所以我创建了ROI
rows, cols, channels = img2.shape
roi = img1[0:rows, 0:cols]
# 现在创建logo的掩码,并同时创建其相反掩码
img2gray = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
cv.imshow('1', img2gray)
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
cv.imshow('2', mask)
mask_inv = cv.bitwise_not(mask)
cv.imshow('3', mask_inv)
# 现在将ROI中logo的区域涂黑
img1_bg = cv.bitwise_and(roi, roi, mask=mask_inv)
cv.imshow('4', img1_bg)
# 仅从logo图像中提取logo区域
img2_fg = cv.bitwise_and(img2, img2, mask=mask)
cv.imshow('5', img2_fg)
# 将logo放入ROI并修改主图像
dst = cv.add(img1_bg, img2_fg)
cv.imshow('6', dst)
img1[0:rows, 0:cols] = dst
cv.imshow('res', img1)
cv.waitKey(0)
cv.destroyAllWindows()

# 掩膜(mask) 在有些图像处理的函数中有的参数里面会有mask参数,即此函数支持掩膜操作,
# 首先何为掩膜以及有什么用,如下:
# 数字图像处理中的掩膜的概念是借鉴于PCB制版的过程,在半导体制造中,
# 许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜(也称作“掩模”),
# 其作用是:在硅片上选定的区域中对一个不透明的图形模板遮盖,
# 继而下面的腐蚀或扩散将只影响选定的区域以外的区域。
# 图像掩膜与其类似,用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,
# 来控制图像处理的区域或处理过程。
# 数字图像处理中,掩模为二维矩阵数组,有时也用多值图像,图像掩模主要用于:
# ①提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,
# 感兴趣区内图像值保持不变,而区外图像值都为0。
# ②屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,
# 或仅对屏蔽区作处理或统计。
# ③结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
# ④特殊形状图像的制作。