Генерация матрицы изображений из кода цепочки Freeman
Предположим, у меня есть код цепи Freeman с 8 направлениями, как показано ниже, в списке Python:
freeman_code = [3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5]
Где направления будут определены следующим образом:
Мне нужно преобразовать это в матрицу изображения переменных размеров со значениями 1 и 0, где 1 будет отображать форму, например, следующим образом:
image_matrix = [
[0, 0, 1, 0, 0, 1],
[0, 0, 0, 1, 0, 1],
[0, 0, 0, 0, 1, 1]
]
Конечно, вышеупомянутое не является точной реализацией вышеуказанного кода Freeman. Есть ли реализация в Python или на любом языке, который достигает этого? Моя идея (в Python): использовать defaultdict defaultdicts с 0 по умолчанию:
ImgMatrixDict = defaultdict(lambda: defaultdict(lambda:0))
а затем начать в средней точке, скажем, ImgMatrixDict[25][25]
, а затем измените значения на 1 в зависимости от значений кода Фримена, когда я пересекаю. После этого я бы преобразовал ImgMatrixDict
в список списков.
Это жизнеспособная идея или существуют какие-либо библиотеки или предложения для реализации этого? Любая идея / псевдокод будет оценен.
PS: Что касается производительности, да, это не важно, поскольку я не буду делать это в режиме реального времени, но обычно код будет иметь длину 15-20 символов. Я предположил, что для этой цели будет достаточно матрицы 50*50.
2 ответа
Если я правильно понимаю ваш вопрос:
import numpy as np
import matplotlib.pyplot as plt
freeman_code = [3, 3, 3, 6, 6, 4, 6, 7, 7, 0, 0, 6]
img = np.zeros((10,10))
x, y = 4, 4
img[y][x] = 1
for direction in freeman_code:
if direction in [1,2,3]:
y -= 1
if direction in [5,6,7]:
y += 1
if direction in [3,4,5]:
x -= 1
if direction in [0,1,7]:
x += 1
img[y][x] = 1
plt.imshow(img, cmap='binary', vmin=0, vmax=1)
plt.show()
Вот решение в Python. Словарь не приспособлен к этой проблеме, вам лучше использовать список для имитации таблицы.
D = 10
# DY, DX
FREEMAN = [(0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1), (1, 0), (1, 1)]
freeman_code = [3, 3, 3, 3, 6, 6, 6, 6, 0, 0, 0, 0]
image = [[0]*D for x in range(D)]
y = D/2
x = D/2
image[y][x] = 1
for i in freeman_code:
dy, dx = FREEMAN[i]
y += dy
x += dx
image[y][x] = 1
print("freeman_code")
print(freeman_code)
print("image")
for line in image:
strline = "".join([str(x) for x in line])
print(strline)
>0000000000
>0100000000
>0110000000
>0101000000
>0100100000
>0111110000
>0000000000
>0000000000
>0000000000
>0000000000
Обратите внимание, что создание изображения является сжатым выражением:
image = []
for y in range(D):
line = []
for x in range(D):
line.append(0)
image.append(line)
Если в один прекрасный день вам потребуется более высокая производительность для больших изображений, есть решения, использующие библиотеку numpy, но требующие хорошего знания основ Python. Вот пример:
import numpy as np
D = 10
# DY, DX
FREEMAN = [(0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1), (1, 0), (1, 1)]
DX = np.array([1, 1, 0, -1, -1, -1, 0, 1])
DY = np.array([0, -1, -1, -1, 0, 1, 1, 1])
freeman_code = np.array([3, 3, 3, 3, 6, 6, 6, 6, 0, 0, 0, 0])
image = np.zeros((D, D), int)
y0 = D/2
x0 = D/2
image[y0, x0] = 1
dx = DX[freeman_code]
dy = DY[freeman_code]
xs = np.cumsum(dx)+x0
ys = np.cumsum(dy)+y0
print(xs)
print(ys)
image[ys, xs] = 1
print("freeman_code")
print(freeman_code)
print("image")
print(image)
Здесь все циклы, созданные с помощью for для предыдущего решения, быстро обрабатываются в C.