---
description: Python | OpenCV | 滤镜 | C++ | ArUco | 视觉跟踪识别 | 标记姿态
---

# Python\_OpenCV(滤镜\_深度传感器\_特征匹配\_视觉跟踪识别\_分类)及其C++ArUco标记姿态计算

### 滤镜

#### 创建黑白铅笔素描

为了获得相机框架的铅笔素描（即黑白图），我们将使用两种图像融合技术，即躲避和刻录。 这些术语是指在传统摄影的打印过程中使用的技术； 在这里，摄影师可以控制暗室照片某些区域的曝光时间，以使其变暗或变暗。 躲避使图像变亮，而刻录使图像变暗。 不应该进行更改的区域用掩膜保护。

如今，现代图像编辑程序（例如Photoshop和Gimp）提供了在数字图像中模拟这些效果的方法。 例如，掩模仍然被用来模仿改变图像的曝光时间的效果，其中具有相对强的值的掩模的区域将使图像更多地曝光，从而使图像变亮。 OpenCV不提供实现这些技术的本机功能。 但是，有了一点见识和一些技巧，我们将得出我们自己的有效实现，可以用来产生漂亮的铅笔素描效果。

如果在Internet上搜索，可能会偶然发现以下通用过程，从RGB（红色，绿色和蓝色）彩色图像中获得铅笔素描：

1. 首先，将彩色图像转换为灰度。
2. 然后，将灰度图像反转以获得负片。
3. 将高斯模糊应用于步骤2中的负片。
4. 通过使用彩色减淡功能，将灰度图像（来自步骤1）与模糊负片（来自步骤3）混合。

第1步到第3步很简单，而第4步可能有些棘手。 让我们先解决这个问题。

#### 理解躲避和烧录

减淡可以减少我们希望在图像A中变得比以前更亮的图像区域的曝光。在图像处理中，我们通常选择或指定需要使用蒙版更改的图像区域。掩膜B是与可应用掩膜的图像尺寸相同的数组（可将其视为一张纸，用于覆盖其中有孔的图像）。 纸上的“孔”在不透明的区域中用零表示255（如果在0-1范围内，则用1表示）。

在诸如Photoshop之类的现代图像编辑工具中，通过使用下面的三元语句（使用索引i作用于每个像素）来实现图像A与掩膜B的颜色减淡：

```bash
((B[i] == 255) ? B[i] :
 min(255, ((A[i] << 8) / (255 - B[i]))))
```

前面的代码实质上是将A \[i]图像像素的值除以B \[i]掩膜像素值的倒数（范围为0-255），同时确保所得的像素值将为 （0，255）的范围，并且我们不除以0。

我们可以将先前看起来复杂的表达式或代码转换为以下朴素的Python函数，该函数接受两个OpenCV矩阵（图像和掩膜）并返回混合图像：

```python
def dodge_naive(image, mask):
 # determine the shape of the input image
 width, height = image.shape[:2]
 # prepare output argument with same size as image
 blend = np.zeros((width, height), np.uint8)
 for c in range(width):
  for r in range(height):
  # shift image pixel value by 8 bits
  # divide by the inverse of the mask
  result = (image[c, r] << 8) / (255 - mask[c, r])
  # make sure resulting value stays within bounds
  blend[c, r] = min(255, result)
 return blend
```

正如您可能已经猜到的那样，尽管先前的代码在功能上可能是正确的，但毫无疑问，它会非常慢。 首先，该函数使用for循环，这在Python中几乎总是一个坏主意。 其次，NumPy数组（Python中OpenCV图像的基本格式）已针对数组计算进行了优化，因此分别访问和修改每个image \[c，r]像素将非常慢。

相反，我们应该意识到<< 8运算与将像素值乘以$2^8$（= 256）相同，并且可以使用cv2.divide函数实现按像素划分。 因此，利用矩阵乘法（更快）的躲避函数的改进版本如下所示：

```python
import cv2
def dodge(image, mask):
 return cv2.divide(image, 255 - mask, scale=256)
```

在这里，我们将躲避函数简化为一行！ 新的躲避函数产生的结果与dodge\_naive相同，但是它比朴素的版本快几个数量级。 除此之外，cv2.divide会自动处理零除，使结果为零，其中255-mask为零。

#### 使用高斯模糊的优化版本

高斯模糊本质上是具有高斯函数的卷积。卷积的特征之一就是它们的关联属性。 这意味着我们先反转图像然后对其进行模糊处理，还是先模糊图像然后对其进行反转都没有关系。

如果我们从模糊的图像开始并将其逆传递给躲避函数，则在该函数内，图像将再次反转（255掩膜部分），实质上产生了原始图像。 如果我们摆脱了这些多余的操作，则经过优化的convert\_to\_pencil\_sketch函数将如下所示：

```python
def convert_to_pencil_sketch(rgb_image):
 gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY)
 blurred_image = cv2.GaussianBlur(gray_image, (21, 21), 0, 0)
 gray_sketch = cv2.divide(gray_image, blurred_image, scale=256)
 return cv2.cvtColor(gray_sketch, cv2.COLOR_GRAY2RGB)
```

为了形象化，我们想将转换后的图像（img\_sketch）与背景图像（画布）轻轻混合，使其看起来就像我们在画布上绘制图像一样。 因此，在返回之前，我们想与画布混合（如果存在）：

```python
if canvas is not None:
 gray_sketch = cv2.multiply(gray_sketch, canvas, scale=1 / 256)
```

我们将最终函数命名为pencil\_sketch\_on\_canvas，它看起来像这样（连同优化）：

```python
def pencil_sketch_on_canvas(rgb_image, canvas=None):
 gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2GRAY)
 blurred_image = cv2.GaussianBlur(gray_image, (21, 21), 0, 0)
 gray_sketch = cv2.divide(gray_image, blurred_image, scale=256)
 if canvas is not None:
 gray_sketch = cv2.multiply(gray_sketch, canvas, scale=1 / 256)
 return cv2.cvtColor(gray_sketch, cv2.COLOR_GRAY2RGB)
```

### 使用深度传感器的手势识别

### 通过特征匹配和透视变换查找对象

### 使用运动结构进行3D场景重建

### OpenCV计算图像

### 视觉跟踪显着对象

### 识别交通信号

### 识别面部表情

### 对象分类和定位

### 检测和跟踪物体

### 源代码

{% content-ref url="../zhi-dian-mi-jin-brief" %}
[zhi-dian-mi-jin-brief](../zhi-dian-mi-jin-brief)
{% endcontent-ref %}
