图片颜色识别
RGB颜色空间

颜色加法
OpenCV的加法是饱和操作,而Numpy添加是模运算
>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> print( cv.add(x,y) ) # 250+10 = 260 => 255
[[255]]
>>> print( x+y ) # 250+10 = 260 % 256 = 4
[4]
import cv2
import numpy as np
image=cv2.imread("./pig.png")
image2=cv2.imread("./cao.png")
image3=cv2.add(image,image2)
image4=image+image2
cv2.imshow("image3",image3)
cv2.imshow("image3",image3)
cv2.waitKey(0)
颜色加权加法
这其实也是加法,但是不同的是两幅图像的权重不同,这就会给人一种混合或者透明的感觉。图像混合的计算公式如下:
g(x) = (1−α)f0(x) + αf1(x)
现在我们把两幅图混合在一起。第一幅图的权重是0.7,第二幅图的权重是0.3。函数cv2.addWeighted()可以按下面的公式对图片进行混合操作。
dst = α⋅img1 + β⋅img2 + γ
image3 = cv2.addWeighted(image1,0.7,image2,0.3,0)
HSV颜色空间

而HSV颜色空间使用色调(Hue)、饱和度(Saturation)和亮度(Value)三个参数来表示颜色,色调H表示颜色的种类,如红色、绿色、蓝色等;饱和度表示颜色的纯度或强度,如红色越纯,饱和度就越高;亮度表示颜色的明暗程度,如黑色比白色亮度低。

符合人类对颜色的感知方式
颜色调整更加直观
维处理有利于计算
hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV) # 转为HSV空间
制作掩膜
掩膜(Mask)是一种在图像处理中常见的操作,它用于选择性地遮挡图像的某些部分,以实现特定任务的目标。掩膜通常是一个二值化图像,并且与原图像的大小相同,其中目标区域被设置为1(或白色),而其他区域被设置为0(或黑色),并且目标区域可以根据HSV的颜色范围进行修改
color_low = np.array([26, 43, 46])#HSV空间黄色最小值
color_high = np.array([34, 255, 255])#HSV空间黄色最大值
#cv2.inRange用于进行多通道图像(尤其是彩色图像)的阈值操作。它将图像中的每个像素值与指定的颜色范围进行比较,并根据比较结果生成一个二值图像(通常称为掩模或标记图像),其中白色像素代表原图中对应位置的像素颜色在设定范围内,而黑色像素则表示不在该范围内。
mask_image_np = cv2.inRange(hsv_image_np, color_low, color_high) # 创建掩膜
与运算
逻辑运算中的“与”运算,其规则是当两个命题都是真时,其结果才为真。而在图像处理中,“与”运算被用来对图像的像素值进行操作。具体来说,就是将两个图像中所有的对应像素值一一进行“与”运算,从而得到新的图像。从上面的图片我们可以看出,掩膜中有很多地方是黑色的,其像素值为0,那么在与原图像进行“与”运算的时候,得到的新图像的对应位置也是黑色的.
通过掩膜与原图的与运算,我们就可以提取出图像中被掩膜覆盖的区域.
color_image_np = cv2.bitwise_and(image_np, image_np, mask=mask_image_np) # 获得颜色识别后的图像
图片颜色替换
path = "./demo.png"
image_np = cv2.imread(path)
hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV) # 转为HSV空间
color_low = np.array([0, 43, 46])
color_high = np.array([10, 255, 255])
mask_image_np = cv2.inRange(hsv_image_np, color_low, color_high) # 创建掩膜
# 替换颜色
image_np[mask_image_np == 255] = (0, 255, 0)
ROI切割
ROI:Region of Interest,翻译过来就是感兴趣的区域
(w, h, _) = image_np.shape
x_min, x_max = 10, 370
y_min, y_max = 150, 390
img_rec = cv2.rectangle(image_np, (x_min - 2, y_min - 2), (x_max + 2, y_max + 2), (0, 0, 255), 2)
#提取目标中的感兴趣区域
ROI_img = image_np[y_min: y_max, x_min: x_max]
图像旋转
单点旋转
图片旋转
将图像里的每个像素点都带入仿射变换矩阵里,从而得到旋转后的新坐标。
仿射变换矩阵可以使用cv2.getRotationMatrix2D(Center,Angle,Scale)
-
Center:表示旋转的中心点,是一个二维的坐标点(x,y)
-
Angle:表示旋转的角度
-
Scale:表示缩放比例,可以通过该参数调整图像相对于原始图像的大小变化
image_np = cv2.imread(path)
img_shape = image_np.shape
# 对图片进行旋转(旋转中心点,旋转角度,缩放比例)
M = cv2.getRotationMatrix2D((img_shape[0] / 2, img_shape[1] / 2), 45, 0.5)
插值方法
旋转、放大、缩小、变形等操作会让像素值多余或缺失,因此需要插值法进行填充
- 最近邻插值 cv2.INTER_NEAREST
通过在源图像中找到最接近目标位置的像素来确定目标位置的像素值。在图像缩放中,如果目标像素在源图像中的位置是整数坐标,那么最近邻插值会直接使用源图像中的对应像素值。如果目标像素在源图像中的位置是一个浮点数坐标,最近邻插值会将其四舍五入到最近的整数坐标,并使用该坐标对应的像素值。
邻插值的优点是实现简单,计算速度快,但缺点是可能会导致图像质量的明显损失
resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_NEAREST)
- 双线性插值 cv2.INTER_LINEAR
考虑了目标位置周围的四个最近邻像素,通过对这四个像素的加权平均来计算目标位置的像素值。这种方法可以在一定程度上提高图像缩放的质量,相比于最近邻插值,它通常能够提供更加平滑的结果。
resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_LINEAR)
- 像素区域插值 cv2.INTER_AREA
当使用像素区域插值方法进行缩小图像时,它就会变成一个均值滤波器,其工作原理可以理解为对一个区域内的像素值取平均值。
当使用像素区域插值方法进行放大图像时,如果图像放大的比例是整数倍,那么其工作原理与最近邻插值类似;如果放大的比例不是整数倍,那么就会调用双线性插值进行放大。
- 双三次插值 cv2.INTER_CUBIC
与双线性插值法相同,该方法也是通过映射,在映射点的邻域内通过加权来得到放大图像中的像素值。不同的是,双三次插值法需要原图像中近邻的16个点来加权。
- Lanczos插值 cv2.INTER_LANCZOS4
Lanczos插值方法与双三次插值的思想是一样的,不同的就是其需要的原图像周围的像素点的范围变成了8*8,并且不再使用BiCubic函数来计算权重,而是换了一个公式计算权重。
边缘填充方式
img2=cv2.warpAffine(img,M,(shape[1],shape[0]),flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT,borderValue=100)
- 边界复制(BORDER_REPLICATE)

- 边界反射(BORDER_REFLECT)

- 边界反思101(BORDER_REFLECT_101)

- 边界常数(BORDER_CONSTANT)

- 边界包裹(BORDER_WRAP)

图片镜像旋转
在OpenCV中,图片的镜像旋转是以图像的中心为原点进行镜像翻转的。也就是说,水平翻转时,图像的左侧和右侧会关于中心点进行交换,垂直翻转时,图像的上侧和下侧会关于中心点进行交换。
-
0:垂直翻转
-
大于0:水平翻转
-
小于0:水平垂直翻转
# 对图片进行镜像操作
mirroring_image = cv2.flip(image_np, 0)
图像缩放
在图像旋转实验中,我们涉及到图像的缩放比例,但该实验中只能按照相同的比例对宽和高进行缩放。而在本实验中我们能够进行x轴和y轴上任意比例的独立缩放。这意味着我们可以单独调整图像在某一个方向上的大小,而不会影响到其他方向上的尺寸。
cv2.resize(image_np, dsize=None, fx=0.6, fy=0.6, interpolation=cv2.INTER_LINEAR)
参数说明:
-
image_np:
这是待缩放的原始图像,它是一个numpy数组表示的图像。 -
None:
这个参数代表目标图像的尺寸(宽度和高度),在这里设置为None意味着我们不直接指定新图像的具体尺寸,而是通过接下来的fx和fy参数来按比例缩放原图像。 -
fx:
这是一个缩放因子,用来控制图像水平方向(宽度)的缩放比例。如果fx=0.6,那么原图像的宽度将缩小到原来宽度的60%。 -
fy:
同样是一个缩放因子,但它控制的是图像垂直方向(高度)的缩放比例。当fy=0.6时,原图像的高度将缩小到原来高度的60%。 -
interpolation:
插值方法,用于决定如何计算新尺寸图像中的像素值。cv2.INTER_LINEAR表示双线性插值,这是一种常用的、平滑且质量相对较高的插值方式,能够较好地保留图像细节和连续性。
图像矫正
透视投影是指将三维空间中的物体投影到二维平面上的过程,这个过程会导致物体在图像中出现形变和透视畸变。透视变换可以通过数学模型来校正这种透视畸变,使得图像中的物体看起来更符合我们的直观感受。通俗的讲,透视变换的作用其实就是改变一下图像里的目标物体的被观察的视角。

getPerspectiveTransform(src,dst)
在该函数中,需要提供两个参数:
src:原图像上需要进行透视变化的四个点的坐标,这四个点用于定义一个原图中的四边形区域。
dst:透视变换后,src的四个点在新目标图像的四个新坐标。
该函数会返回一个透视变换矩阵,得到透视变化矩阵之后,使用warpPerspective()函数即可进行透视变化计算,并得到新的图像
cv2.warpPerspective(src, M, dsize, flags, borderMode)
数需要提供如下参数:
src:输入图像。
M:透视变换矩阵。这个矩阵可以通过getPerspectiveTransform函数计算得到。
dsize:输出图像的大小。它可以是一个Size对象,也可以是一个二元组。
flags:插值方法的标记。
borderMode:边界填充的模式。
image_np = cv2.imread(path)
img_shape = image_np.shape
# 原图中卡片的四个角点
pts1 = np.float32([[178, 100], [487, 134], [124, 267], [473, 308]])
img_line = image_np
cv2.line(img_line, pts1[0].astype(np.int64).tolist(), pts1[1].astype(np.int64).tolist(), (0, 0, 255), 2,cv2.LINE_AA)
cv2.line(img_line, pts1[0].astype(np.int64).tolist(), pts1[2].astype(np.int64).tolist(), (0, 0, 255), 2,cv2.LINE_AA)
cv2.line(img_line, pts1[3].astype(np.int64).tolist(), pts1[1].astype(np.int64).tolist(), (0, 0, 255), 2,cv2.LINE_AA)
cv2.line(img_line, pts1[3].astype(np.int64).tolist(), pts1[2].astype(np.int64).tolist(), (0, 0, 255), 2,cv2.LINE_AA)
# 变换后分别在左上、右上、左下、右下四个点
pts2 = np.float32([[0, 0], [img_shape[1], 0], [0, img_shape[0]], [img_shape[1], img_shape[0]]])
pts = cv2.getPerspectiveTransform(pts1, pts2) # 生成透视变换矩阵
correct_image = cv2.warpPerspective(image_np, pts, (img_shape[1], img_shape[0]), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REFLECT_101) # 进行透视变换
# 返回处理正确后的内容
cv2.imshow("image_np", image_np)
cv2.imshow('img_line', img_line)
cv2.imshow("correct_image", correct_image)
cv2.waitKey(0)

625

被折叠的 条评论
为什么被折叠?



