[Обработка компьютерного зрения 3] Базовая обработка изображений

задняя часть

Это 3-й день моего участия в августовском испытании обновлений, подробности о событии:Испытание августовского обновления

базовая обработка изображений

1. Фрагмент изображения

Ранее мы узнали, что изображение в opencv на самом деле является массивом ndarray, и мы работаем с массивом ndarray для работы с изображением. Давайте сначала рассмотрим поиск среза, который мы используем очень часто.

(1) Срезы одномерных массивов

Давайте посмотрим на синтаксис нарезки.Для одномерного массива мы можем получить элементы с 0-го по 4-й с помощью следующих операций:

array[0:5]

Из вышеизложенного мы можем знать, что наша операция нарезки остается закрытой и открытой справа. Вышеупомянутая операция нарезки может быть сокращена следующим образом:

array[:5]

Если мы не установим первое значение, это означает нарезку с самого начала. Конечно, мы также можем опустить второе значение, в этом случае смысл в том, чтобы получить последний элемент, например, следующая операция:

array[3:]

Давайте рассмотрим операцию нарезки на практическом примере:

import numpy as np
# 创建一个一维的ndarray数组,数据为[0, 1, 2, 3, 4, 5, 6, 7]
array = np.array([0, 1, 2, 3, 4, 5, 6, 7])
# 取0到4个元素
print(array[0:5])
print(array[:5])
# 取第3个到最后一个元素
print(array[3:])

Результат выглядит следующим образом:

[0 1 2 3 4]
[0 1 2 3 4]
[3 4 5 6 7]

Мы можем резюмировать операцию нарезки как:

# 左闭右开
array[start: end-1]

Когда мы начинаем с 0-го и получаем последнее, соответствующее значение можно опустить.

(2) Нарезка двумерных массивов

При обработке изображений нас больше интересует нарезка двумерных массивов. Его синтаксис очень похож на одномерные массивы. Чтобы облегчить понимание, мы напрямую используем изображения для нарезки, например следующее изображение:

在这里插入图片描述

Синтаксис для нарезки двумерного массива следующий:

array[start:end-1, start:end-1]

Теперь нам нужно прояснить, что левая часть — это перехват высоты, а правая часть — перехват ширины. Теперь я хочу захватить левую половину изображения, операция должна быть следующей:

import cv2
# 读取图片
img = cv2.imread('xyql.jpg')
# 获取图片的宽,并除2
width = img.shape[1]//2
# 对图片进行切片,截取左半部分
left = img[:, :width]
# 显示图像三步骤
cv2.imshow('left', left)
cv2.waitKey(0)
cv2.destroyAllWindows()

где код для нарезки:

left = img[:, :width]

Один слева - это высота перехвата, нам нужно все перехватить, поэтому оба значения могут быть опущены. Справа, нам нужно только перехватить левую половину, поэтому значение слева может быть опущено, а значение справа - это ширина, которую мы рассчитали ранее. Ниже приведена диаграмма эффекта:

在这里插入图片描述

Здесь следует отметить, что цветные изображения на самом деле трехмерны, но мы не манипулируем третьим измерением.

2. Замените область изображения

Теперь, когда мы знаем, как нарезать, мы можем заменить указанную область. Однако следует отметить, что форма заменяемой и замененной областей должна быть одинаковой, то есть атрибут формы должен быть одинаковым. Например, если я хочу заменить область 100*100 в левом верхнем углу картинки на белый цвет, то я могу сделать следующее:

import cv2
import numpy as np
img = cv2.imread('1.jpg')
# 创建一个100*100的白色图像
replace_img = np.ones((100, 100), dtype=np.uint8)*255
# 将图片左上角100*100区域替换
img[:100, :100] = replace_img

После запуска вы обнаружите следующую ошибку:

    img[:100, :100] = replace_img
ValueError: could not broadcast input array from shape (100,100) into shape (100,100,3)

Это означает, что образ (100, 100) не может быть преобразован в образ (100, 100, 3), то есть форма не совпадает. На это нужно обратить особое внимание при замене, мы внесем некоторые изменения в приведенный выше код:

import cv2
import numpy as np
img = cv2.imread('xyql.jpg')
replace_img = np.ones((100, 100, 3), dtype=np.uint8)*255
img[:100, :100] = replace_img

* Таким образом мы можем успешно заменить, эффект следующий:

在这里插入图片描述

На самом деле с помощью вышеперечисленных операций мы можем добиться «двойного» эффекта, давайте посмотрим.

3. Для достижения «двойного» эффекта

Сначала мы подготовим два снимка, чтобы камера сделала два снимка без движения, например следующие два:

在这里插入图片描述

Вот два снимка, которые я только что сделал, так как камера не двигалась, фон должен быть таким же. Мы можем объединить два сна в одно изображение с помощью следующего кода:

import cv2
# 读取两张图片
img1 = cv2.imread('mh1.JPG')
img2 = cv2.imread('mh2.JPG')
# 求出宽的中间值
mid = img1.shape[1]//2
# 把mh2的右半边替换到mh1的右半部分
img1[:, mid:] = img2[:, mid:]
# 将拼接后的图片保存到本地
cv2.imwrite('result.jpg', img1)

Приведенный выше код очень прост, нам нужно только обратить внимание на следующее предложение:

img1[:, mid:] = img2[:, mid:]

Формы img1 и img2 одинаковые, и перехватываемая область тоже одинаковая, так что проблем с заменой нет. Наконец мы проходим:

cv2.imwrite('result.jpg', img1)

Сохраните изображение. Поскольку мы работаем непосредственно с img1, мы просто сохраняем img1 напрямую. Вот наш рендеринг:

在这里插入图片描述

Я должен сказать еще одну вещь, у меня есть только одна мечта.

4. numpy генерирует массив

В предыдущей статье мы использовали следующий код для генерации массива:

im = np.zeros((3, 3, 1), dtype=np.uint8)

Для массива numpy мы генерируем массив, но для opencv мы генерируем изображение. Давайте посмотрим на некоторые операции, которые numpy генерирует массивы.

(1) np.ones

Мы можем сгенерировать массив со всеми 1 элементами с помощью функции numpy, например, следующий код:

np.ones((100, 100), dtype=np.uint8)

one получает два параметра, первый параметр — форма массива, а второй — тип элемента массива, где np.uint8 представляет [беззнаковое 8-битное целое], то есть диапазон находится между (0-255 ). Мы можем отобразить приведенное выше изображение с помощью opencv:

import cv2
import numpy as np
# 生成一个100*100的图片,每个元素的值都为1
img = np.ones((100, 100), dtype=np.uint8)
cv2.imwrite('result.jpg', img)

Схема эффекта выглядит следующим образом:

在这里插入图片描述

Поскольку 1 очень близко к 0, цвет изображения близок к черному. Мы можем работать с каждым элементом, выполнив следующие действия:

import cv2
import numpy as np
img = np.ones((100, 100), dtype=np.uint8) * 127
cv2.imwrite('result.jpg', img)

После того, как мы сгенерируем массив с элементом 1, как умножить на 127, чтобы каждый элемент можно было умножить на 127. В настоящее время каждый элемент массива равен 127, и следующий эффект отображения:

在这里插入图片描述

Конечно, наше изображение двумерное, то есть изображение в градациях серого для opencv. Если мы хотим создать цветное изображение, мы можем создать трехмерное изображение, которое мы продолжим объяснять позже.

(2) np.zeros

Нет никакой разницы между np.zeros и единицами, за исключением того, что содержимое его элемента равно 0. Давайте кратко рассмотрим:

import numpy as np
img = np.zeros((5, 5), dtype=np.uint8)
print(img)

Для удобства просмотра мы напрямую генерируем простой массив, и на выходе получается следующее:

[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]]

Другие уже не разрабатываются.