Итак, что я пытаюсь сделать, это взять изображение (скажем, 100x100) и сделать ядро 5x5 поверх изображения:
kernel = np.ones((5, 5), np.float32)/25
а затем выводить массив для каждой итерации ядра (как в cv2.filter2D), например:
kernel_vals.append(np.array([[indexOfKernelIteration], [newArrayOfEditedKernelValues]]))
Чего мне не хватает, так это того, как заставить его перебирать изображение и выводить значения пикселей нового «изображения», которое будет создано:
img = cv2.filter2D(image, -1, kernel)
Я просто хочу, чтобы для каждого ядра выходные данные, отображаемые на новом изображении, помещались в массив «kernel_vals».
^ НЕ В ИЗОБРАЖЕНИЕ
Прикрепленное изображение для наглядности.
@stateMachine Спасибо за комментарий! Это похоже на то, что я хочу сделать, но я думаю, что я действительно застрял на проблеме получения пикселей в массив в целом. Не мог этого увидеть, потому что слишком увлекся методом filter2d, лол. Однако я понимаю, о чем вы говорите, и сначала я думал именно об этом, потому что я хочу найти место наибольшей концентрации белых пикселей на изображении. Я уверен, что, вероятно, есть более простой способ, но мне было предложено использовать ядро, по крайней мере, для того, чтобы заставить работать голую функциональность.
imread
возвращает np.array
, поэтому, если я понимаю, что вы хотите сделать, у вас есть решение в вопросе. Для полноты картины см. приведенный ниже код.
import cv2
img = cv2.imread("image.png", cv2.IMREAD_GRAYSCALE)
print(type(img))
print(img[:10, :10])
kernel = np.ones((5, 5), np.float32)/25
kernel_vals = cv2.filter2D(img, -1, kernel)
print(kernel_vals[:10, :10])
И вывод (с добавленными новыми строками для удобства чтения)
<class 'numpy.ndarray'>
[[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 0 255 255 255 0 255 255]
[255 255 255 0 255 255 255 0 255 255]
[255 255 255 0 255 255 255 0 255 255]
[255 255 255 0 255 255 255 0 255 255]
[255 255 255 0 255 255 255 0 255 255]
[255 255 255 0 255 255 255 0 255 255]
[255 255 255 0 255 255 255 0 255 255]]
[[255 255 255 255 255 255 255 255 255 255]
[255 245 245 245 245 235 245 245 245 235]
[255 235 235 235 235 214 235 235 235 214]
[255 224 224 224 224 194 224 224 224 194]
[255 214 214 214 214 173 214 214 214 173]
[255 204 204 204 204 153 204 204 204 153]
[255 204 204 204 204 153 204 204 204 153]
[255 204 204 204 204 153 204 204 204 153]
[255 204 204 204 204 153 204 204 204 153]
[255 204 204 204 204 153 204 204 204 153]]
Теперь, поскольку kernel_vals
— это np.array
, вы можете сгладить его, превратить в список или манипулировать им любым другим способом.
Я думаю, что OP спрашивает, как воспроизвести функциональность filter2d вручную, используя функции на основе python/numpy.
@stateMachine Я не понимаю, как ОП спрашивает о реализации 2D-свертки вручную, но если это так (и, надеюсь, они могут прояснить), на этот вопрос был дан ответ здесь (пустой ответ) и здесь (менее громоздко)
@AlexP Спасибо за ответ! Я спрашиваю в основном, как преобразовать изображение в числовой массив. Я думаю, вы сделали в основном то, что я хотел сделать; Я хотел пройтись по изображению, уменьшив его и сжав область чисел 5x5 в 1 "пиксель". Причина этого заключается в том, чтобы в конечном итоге попытаться найти область 5x5 с наибольшим процентом белого или «255» пикселей. Я думаю, что это на правильном пути, но я не уверен, что именно показывает новый массив. Если я правильно понимаю, это образ после того, как ядро пробежится по нему, но делает ли это то, что я хочу? С точки зрения нахождения макс.
@AlexP несмотря ни на что, вы были очень полезны! По какой-то причине я не смог найти метод imread
самостоятельно. Вероятно, потому что я новичок в Computer Vision и застрял в выяснении того, как изменить метод filter2D. Об этом мне не нужно думать, потому что я могу превратить изображение в np.array
с самого начала.
@ZacharyPartlo Новый массив в каждой ячейке содержит результат свертки с указанной ячейкой в качестве центра. Поскольку ваше ядро является средним (или усредняющим) фильтром, результат показывает среднюю интенсивность света (поскольку это изображение в градациях серого) локально для каждой ячейки. Если теперь вы хотите найти «самую белую» область 5x5, вам просто нужен один, несколько или все индексы результирующей матрицы с максимальным значением в матрице, что достаточно просто с numpy. Итак, основываясь на вашем комментарии, я бы сказал, что это именно то, что вы хотите. Кроме того, подумайте о том, чтобы проголосовать и принять ответ, если он решил вашу проблему.
@AlexP Хорошо! Спасибо! Я бы проголосовал, если бы мог. Обычно я просто тащусь на SO, но сегодня был мой первый пост! Я приму ответ, хотя!
@AlexP другая проблема заключается в том, что я пытаюсь передать фоновое вычитаемое изображение (не имя файла) в cv2.imread
. Он поддерживает только прямые имена файлов, верно?
@ZacharyPartlo, что вы имеете в виду под «фоновым вычтенным изображением»? Но да, imread
принимает путь к файлу изображения
@AlexP Я использую cv2.bgsegm.createBackgroundSubtractorMOG()
, чтобы замаскировать каждый кадр видео, а затем найти местонахождение наибольшего количества пустого пространства. Я не знаю, как использовать imread
без пути к файлу. Или, может быть, в Computer Vision есть другой инструмент? Я искал документы и онлайн, но ничего не нашел.
@ZacharyPartlo вам не нужно использовать imread
, если это не относится к вашему варианту использования. Когда вы примените вычитатель к кадру, какой будет результат? Основываясь на приведенном выше коде, как вы можете проверить, каков результат? И что вы хотите, чтобы это было? Используйте type
, и вы увидите, что это также np.array
, а это именно то, что вам нужно. Всегда пробуйте сами и проверяйте/понимайте, что вы вкладываете и что получается
@AlexP хорошо, спасибо! Вы были очень полезны! Я буду иметь в виду эти вопросы при тестировании в будущем!
Одним из способов реализации свертки, хотя и очень медленным, будет обход изображения при извлечении окрестности ядра на каждой итерации. Для каждого входного пикселя вы можете разрезать область
5 x 5
, выполнять линейные комбинации между пикселями и отправлять полученный пиксель на новое изображение (или «холст»). Конечно, в Python проверка типов для каждой итерации цикла выполняется довольно медленно. Честно говоря, я не знаю, можно ли векторизовать эту операцию с помощью функцийnumpy
, но вы могли бы, по крайней мере, использоватьnumba
для ускорения процесса. Надеюсь, кто-то достаточно сообразительный сможет вмешаться.