OpenCV实战(基础知识三)

简介

OpenCV是一个流行的开源计算机视觉库,由英特尔公司发起发展。它提供了超过2500个优化算法和许多工具包,可用于灰度、彩色、深度、基于特征和运动跟踪等的图像处理和计算机视觉应用。OpenCV主要使用C++语言编写,同时也支持Python、Java、C等语言。由于其开源和广泛使用的特点,在计算机视觉和机器学习领域得到了广泛的应用。

1.图像阈值

图像阈值化(Image Thresholding)是一种常用的图像处理技术,它用来将图像分割成不同的区域或提取出感兴趣的目标。阈值化基于图像中像素灰度值的阈值进行二值化处理,将像素分为两个类别:满足条件的像素为一个类别,不满足条件的像素为另一个类别 。

图像阈值化的主要步骤如下:

  1. 灰度化:将彩色图像转换为灰度图像,这样每个像素只有一个灰度值。

  2. 选择阈值:根据应用需求和图像特性,选择一个适当的阈值。

  3. 阈值化处理:将图像中的每个像素与阈值进行比较,并根据比较结果设置像素的输出值。

在 OpenCV 中,可以使用 cv2.threshold() 函数来执行图像阈值化操作。

ret, dst = cv2.threshold(src, thresh, maxval, type[, dst])

 

  1. ret:阈值化操作的阈值,即根据阈值对图像进行二值化后得到的阈值。

  2. dst:阈值化后的输出图像,即应用阈值化操作后得到的二值图像。

其中,src 是输入的源图像,thresh 是用于二值化的阈值,maxval 是输出图像中设置为最大值的像素值,type 是阈值化的类型。

除了上述两个返回参数外,你还可以选择性地传递额外的 dst 参数作为输出图像的占位符,以便在函数调用时直接指定输出图像的尺寸和数据类型。如果未提供 dst 参数,函数将会创建一个与输入图像 src 相同尺寸和数据类型的输出图像。

请注意,阈值化类型 type 可以是以下选项之一:

  • cv2.THRESH_BINARY:二值阈值化,大于阈值的像素值设为 maxval,小于等于阈值的像素值设为 0。

  • cv2.THRESH_BINARY_INV:反二值阈值化,大于阈值的像素值设为 0,小于等于阈值的像素值设为 maxval

  • cv2.THRESH_TRUNC:截断阈值化,大于阈值的像素值设为阈值,小于等于阈值的像素值保持不变。

  • cv2.THRESH_TOZERO:零阈值化,大于阈值的像素值保持不变,小于等于阈值的像素值设为 0。

  • cv2.THRESH_TOZERO_INV:反零阈值化,大于阈值的像素值设为 0,小于等于阈值的像素值保持不变。

import cv2
import matplotlib as plt
import numpy as np

# 读取图像
image = cv2.imread('image/1.jpg')

# 使用不同阈值化方法进行图像处理
# 阈值为127,最大值为255
# cv2.THRESH_BINARY: 二值阈值化
ret, img = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
# cv2.THRESH_BINARY_INV: 反二值阈值化
ret, img1 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY_INV)
# cv2.THRESH_TRUNC: 截断阈值化
ret, img2 = cv2.threshold(image, 127, 255, cv2.THRESH_TRUNC)
# cv2.THRESH_TOZERO: 零阈值化
ret, img3 = cv2.threshold(image, 127, 255, cv2.THRESH_TOZERO)
# cv2.THRESH_TOZERO_INV: 反零阈值化
ret, img4 = cv2.threshold(image, 127, 255, cv2.THRESH_TOZERO_INV)

# 将多个处理后的图像水平拼接在一起
result = np.hstack([img, img1, img2])

# 显示结果图像
cv2.imshow('IMG', result)
cv2.waitKey()
cv2.destroyAllWindows()

OpenCV实战(基础知识三)_第1张图片

这边展示前三种的效果,有兴趣可以全部尝试一下

2.形态学

2.1 膨胀操作

1、什么是膨胀与腐蚀

膨胀与腐蚀属于形态学范围,具体的含义根据字面意思来理解即可。但是更形象的话就是“增肥”与“减肥”。

它们的用途就是用来处理图形问题上。总结性的来说: + 膨胀用来处理缺陷问题; + 腐蚀用来处理毛刺问题。

膨胀就是把缺陷给填补了,腐蚀就是把毛刺给腐蚀掉了。这里其实说的并不严谨,也是为了大家理解方便。下面我们就用实例来进行演示。

dst = cv2.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

参数说明:

  • src:输入图像,可以是灰度图像或彩色图像,数据类型为 uint8
  • kernel:膨胀操作的结构元素,用于定义膨胀的形状和大小。通常为矩形、十字形或椭圆形。
  • dst:输出图像,与输入图像具有相同的大小和类型,可选参数。
  • anchor:锚点位置,默认为 (-1, -1),表示锚点位于结构元素的中心点。
  • iterations:膨胀操作的迭代次数,默认为 1。
  • borderType:边界扩展类型,默认为 cv2.BORDER_CONSTANT
  • borderValue:边界值,在使用 cv2.BORDER_CONSTANT 边界扩展类型时有效,默认为 0。
import cv2
import numpy as np

image = cv2.imread('image/img.png')

kernel = np.ones((3 * 3), dtype=np.uint8)
dilate = cv2.dilate(image, kernel, 1)

result = np.hstack([image, dilate])

cv2.imshow('IMG', result)
cv2.waitKey()
cv2.destroyAllWindows()

可以看到右边的线条比左边的要粗一下,这个就是膨胀操作

OpenCV实战(基础知识三)_第2张图片

kernel = np.ones((4 * 4), dtype=np.uint8) 更改卷积核大小
dilate = cv2.dilate(image, kernel, 3)更改迭代次数

二者均可使膨胀效果更为明显

OpenCV实战(基础知识三)_第3张图片

 

2.2 腐蚀操作

腐蚀操作和膨胀操作相反,也就是将毛刺消除

这边的函数参数和膨胀的是一样的这里就不做详细说明了。

import cv2
import numpy as np

image = cv2.imread('image/img.png')

# kernel = np.ones((3 * 3), dtype=np.uint8)
# dilate = cv2.dilate(image, kernel, 1)
# result = np.hstack([image, dilate])
kernel = np.ones((3*3),dtype=np.uint8)
erosion = cv2.erode(image,kernel,1)
result = np.hstack([image,erosion])

cv2.imshow('IMG', result)
cv2.waitKey()
cv2.destroyAllWindows()

OpenCV实战(基础知识三)_第4张图片

 

2.3 开运算和闭运算

开运算:先腐蚀,在膨胀 闭运算:先膨胀,在腐蚀

我们在上面的膨胀和腐蚀的图片中可以看到,图片大小程度上都受到了损失,字体信息缺失或者变粗等等。如果我们不想更改原有信息,即字体粗细。那么我们可以使用上面的两种运算。例如开运算,先对字体进行变细,在对字体进行变粗,整体上字体粗细不会发生变化。毛刺信息在腐蚀的时候就已经消除了,膨胀也不会膨胀出多余信息。

2.3.1、开运算

dst = cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src:输入图像,可以是灰度图像或彩色图像,数据类型为 uint8
  • op:形态学操作类型,可选项包括 cv2.MORPH_ERODE(腐蚀)、cv2.MORPH_DILATE(膨胀)、cv2.MORPH_OPEN(开运算)、cv2.MORPH_CLOSE(闭运算)等。
  • kernel:形态学操作的结构元素,用于定义操作的形状和大小。通常为矩形、十字形或椭圆形。
  • dst:输出图像,与输入图像具有相同的大小和类型,可选参数。
  • anchor:锚点位置,默认为 (-1, -1),表示锚点位于结构元素的中心点。
  • iterations:形态学操作的迭代次数,默认为 1。
  • borderType:边界扩展类型,默认为 cv2.BORDER_CONSTANT
  • borderValue:边界值,在使用 cv2.BORDER_CONSTANT 边界扩展类型时有效,默认为 0。

 

import cv2
import numpy as np

image = cv2.imread('image/img_1.png')

kernel = np.ones((4 * 4), dtype=np.uint8)
# dilate = cv2.dilate(image, kernel, 1)
# result = np.hstack([image, dilate])

# kernel = np.ones((4 * 4), dtype=np.uint8)

opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel, 1)
result = np.hstack((image, opening))

# erosion = cv2.erode(image, kernel, 2)
# result = np.hstack([image, erosion])

cv2.imshow('IMG', result)
cv2.waitKey()
cv2.destroyAllWindows()

OpenCV实战(基础知识三)_第5张图片

 我们发现大部分毛刺已经消除,而且字体信息也没有发生变化,这也就是我们想要的效果。虽然仍然有一部信息没有被清除,我们只需要调整卷积核的大小就可以实现。

2.3.2、闭运算

OpenCV实战(基础知识三)_第6张图片

字体不改变的前提下,我们把字体缺陷信息补全。 

3.梯度计算

梯度计算主要显示的是边缘信息。计算的方法:

膨胀的图像 - 腐蚀的图像

我们明显的看出,用大一圈的图像减去小一圈的图像正好就是边缘的信息。

gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

OpenCV实战(基础知识三)_第7张图片 

 

我们可以看出来,我们形成了一个空心的字体样式

4、高帽和黑帽

高帽计算

我们知道开运算的结果就是去除毛刺,我们原始图像减去开运算结果就是我们要消除的毛刺信息。

 可以看出来,所有的毛刺信息我们全部提取了出来。

OpenCV实战(基础知识三)_第8张图片

  可以看出来,所有的毛刺信息我们全部提取了出来。

黑帽操作

高帽操作显示毛刺,那么黑帽就是显示缺陷

高帽操作显示毛刺,那么黑帽就是显示缺陷。

OpenCV实战(基础知识三)_第9张图片

这里我们看的不是很明显,我们只需要只要黑帽所处理的问题是什么。针对不同的场景应用不用的方法。 

 

你可能感兴趣的:(opencv,人工智能,计算机视觉)