Какой самый быстрый и надежный способ обнаружения горизонтальной красной лазерной линии в изображении с помощью Python? Я работаю над небольшим проектом, связанным с 3D-лазерным сканированием, и мне нужно иметь возможность обнаруживать лазер в изображении, чтобы рассчитать расстояние от его искажения.
Для начала, у меня есть два изображения, опорное изображение А известно, не содержат лазерной линии, и изображение B, который, безусловно, содержит лазерную линию, возможно, искаженное. например.
Пример изображения A:
Пример изображения B:
Так как это RGB, но лазер красный, я удаляю некоторый шум, удаляя синие и зеленые каналы, используя эту функцию:
from PIL import Image
import numpy as np
def only_red(im):
"""
Strips out everything except red.
"""
data = np.array(im)
red, green, blue, alpha = data.T
im2 = Image.fromarray(red.T)
return im2
Это дает мне следующие изображения:
Затем я пытаюсь устранить больше шума, используя разницу этих двух изображений с помощью PIL.ImageChops.difference()
. В идеальном случае экспозиция между двумя изображениями будет одинаковой, в результате чего разница не будет содержать ничего, кроме лазерной линии. К сожалению, поскольку лазер добавляет свет, экспозиция и общая яркость каждого изображения существенно различаются, что приводит к различию, которое по-прежнему имеет значительный шум. например.
Мой последний шаг - сделать "лучшее предположение" относительно того, где находится линия. Поскольку я знаю, что линия будет грубо горизонтальной, а лазерная линия должна быть самой яркой на изображении, я просматриваю каждый столбец и нахожу строку с самым ярким пикселем, который, как я полагаю, является лазерной линией. Код для этого:
import os
from PIL import Image, ImageOps
import numpy as np
x = Image.open('laser-diff.png', 'r')
x = x.convert('L')
out = Image.new("L", x.size, "black")
pix = out.load()
y = np.asarray(x.getdata(), dtype=np.float64).reshape((x.size[1], x.size[0]))
print y.shape
for col_i in xrange(y.shape[1]):
col_max = max([(y[row_i][col_i], row_i) for row_i in xrange(y.shape[0])])
col_max_brightness, col_max_row = col_max
print col_i, col_max
pix[col_i, col_max_row] = 255
out.save('laser-line.png')
Все, что мне нужно для выполнения вычисления расстояния, - это массив значений col_max
, но laser-line.png
помогает мне визуализировать успех и выглядит так:
Как вы можете видеть, оценка довольно близка, но у нее все еще есть некоторый шум, в основном на левой стороне изображения, где лазерная линия поглощается матовой черной отделкой.
Что я могу сделать, чтобы улучшить свою точность и/или скорость? Я пытаюсь запустить это на платформе ARM, такой как Raspberry Pi, поэтому я беспокоюсь, что мой код может быть слишком неэффективным, чтобы хорошо работать.
Я не полностью знаком с матричными функциями Numpy, поэтому мне пришлось успеть на медленный цикл, чтобы сканировать каждый столбец, а не что-то более эффективное. Есть ли быстрый способ найти строку с самым ярким пикселем на столбец в Numpy?
Кроме того, существует ли надежный способ выравнивания изображений перед выполнением разности без затемнения лазерной линии?