Как я могу получить изображение холста для обнаружения и телепортироваться на другое изображение холста? - PullRequest
0 голосов
/ 12 декабря 2018

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

То, что я хочу сделать, это когда нажата Build Road(vertical) или Build Road(horizontal), этообнаружит любое уже существующее изображение этой дороги и поместит его вертикально или горизонтально к нему на основе нажатой кнопки.Я знаю, это звучит немного неправдоподобно, но вот мой код:

from tkinter import *


root = Tk()
root.title("root")


road1 = PhotoImage(file=r"road1.png")
road2 = PhotoImage(file=r"road2.png")
road3 = PhotoImage(file=r"intersection.png")

canvas = Canvas(root, width=500, height=400, bg='green')

button_frame = Frame(root)

button_frame.pack(side="left", fill="y")
canvas.pack(side="right", fill="both", expand=True)
roadstart = canvas.create_image(100, 0, image=road1)

clickedv = None
clickedh = None
clickedm = None


def buildroadv():
    global clicked
    clickedv = False
    road = canvas.create_image(50, 50, image=road1)
    def move(event):
        global clickedv
        if clickedv == False:
            x = event.x
            y = event.y
            canvas.coords(road, x, y)
    def placeroad(event):
        global clickedv
        clickedv = True
    canvas.tag_bind(road, "<Motion>", move)
    canvas.tag_bind(road, "<ButtonPress-1>", placeroad)

def buildroadh():
    global clickedh
    clickedh = False
    road = canvas.create_image(50, 50, image=road2)
    def move(event):
        global clickedh
        if clickedh == False:
            x = event.x
            y = event.y
            canvas.coords(road, x, y)
    def placeroad(event):
        global clickedh
        clickedh = True
    canvas.tag_bind(road, "<Motion>", move)
    canvas.tag_bind(road, "<ButtonPress-1>", placeroad)

def buildroadm():
    global clickedm
    clickedm = False
    road = canvas.create_image(50, 50, image=road3)
    def move(event):
        global clickedm
        if clickedm == False:
            x = event.x
            y = event.y
            canvas.coords(road, x, y)
    def placeroad(event):
        global clickedm
        clickedm = True
    canvas.tag_bind(road, "<Motion>", move)
    canvas.tag_bind(road, "<ButtonPress-1>", placeroad)



button1 = Button(button_frame, text="Build Road (vertical)", command=buildroadv)
button2 = Button(button_frame, text="Build Road (horizontal)", command=buildroadh)
button3 = Button(button_frame, text="Build Road (intersection)", command=buildroadm)
button4 = Button(button_frame, text="Build -")
button5 = Button(button_frame, text="Build -")
button6 = Button(button_frame, text="Build -")
button7 = Button(button_frame, text="Build -")
button8 = Button(button_frame, text="Build -")


button1.pack(side="top", fill="x")
button2.pack(side="top", fill="x")
button3.pack(side="top", fill="x")
button4.pack(side="top", fill="x")
button5.pack(side="top", fill="x")
button6.pack(side="top", fill="x")
button7.pack(side="top", fill="x")
button8.pack(side="top", fill="x")

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

Надеюсь, этого достаточно.Я прошу прощения за такой конкретный вопрос / широкий ответ.

1 Ответ

0 голосов
/ 13 декабря 2018

Хорошо, так что это, вероятно, сумасшедший перебор для того, что вы делаете.Вероятно, вы можете просто использовать координаты из вашего последнего щелчка, чтобы извлечь размеры и местоположение вашей дороги.К сожалению, без доступа к изображениям я не могу проверить это, поэтому я решил предложить вам более общее решение, которое будет работать, даже если вы загрузите изображение, подобное тому, которое вы предоставили, на холст, где нет кликовпомнить.Кроме того, как отмечалось в некоторых комментариях, если вы уже знаете координаты и размеры ваших дорожных блоков, их размещение тривиально.Просто установите новую дорогу для размещения в соответствующем месте на основе ваших сохраненных значений.Это становится немного сложнее, когда вы не знаете, где находятся дороги, то есть когда вы смотрите на необработанное изображение.Это проблема, на которую я буду смотреть.Основная тактика, которую я выбрал, состоит в том, чтобы решить эту проблему, как любую другую проблему обработки изображения / компьютерного зрения, и найти дороги как объекты на изображении.

Первый шаг - это изолировать дороги.Чтобы сделать это, вы можете использовать фильтр sobel, чтобы найти ребра, затем установить порог и заливку, чтобы превратить их в сплошные блоки:

import imageio
import skimage
import numpy
import scipy.ndimage.filters
import skimage.io
import skimage.filters
import skimage.morphology


image = imageio.imread(r'C:\Users\Jeremiah\Pictures\roads.PNG')
image_array = numpy.float64(image)

#Sobel Filter for color image.  First the kernel is applied to the RGB values, then some linear algebra is done to marry the results together and apply them to the image as a whole.

R_x = scipy.ndimage.filters.correlate(image_array[:, :, 0], [[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
G_x = scipy.ndimage.filters.correlate(image_array[:, :, 1], [[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
B_x = scipy.ndimage.filters.correlate(image_array[:, :, 2], [[1, 2, 1], [0, 0, 0], [-1, -2, -1]])

R_y = scipy.ndimage.filters.correlate(image_array[:, :, 0], [[1, 0 , -1], [2, 0, -2], [1, 0, -1]])
G_y = scipy.ndimage.filters.correlate(image_array[:, :, 1], [[1, 0 , -1], [2, 0, -2], [1, 0, -1]])
B_y = scipy.ndimage.filters.correlate(image_array[:, :, 2], [[1, 0 , -1], [2, 0, -2], [1, 0, -1]])

Jacobian_x = R_x**2 + G_x**2 + B_x**2
Jacobian_y = R_y**2 + G_y**2 + B_y**2
Jacobian_xy = R_x * R_y + G_x * G_y + B_x * B_y
Determinant = numpy.sqrt(numpy.fabs((Jacobian_x**2) - (2 * Jacobian_x * Jacobian_y) + (Jacobian_y**2) + 4 * (Jacobian_xy**2)))
Maximum_Eigenvalue = (Jacobian_x + Jacobian_y + Determinant) / 2
Edges = numpy.sqrt(Maximum_Eigenvalue)

#A threshold is set, and a binary image is produced that sets everything above the threshold to 255 and everything below it to 0.

Threshold = skimage.filters.threshold_mean(Edges)
Binary_Image = Edges > Threshold   

#The holes in the objects are filled in, so that each road is a solid block.

Filled_Holes = scipy.ndimage.morphology.binary_fill_holes(Binary_Image)

Далее вы пометите свои блоки:

labeled_Edges, features = scipy.ndimage.label(Filled_Holes)

Теперь, когда вы пометили объекты на изображении, вы можете использовать срезы labeled_Edges в качестве индексов того, где этот блок начинается и заканчивается.features дает вам количество объектов на изображении.Например:

sliced = scipy.ndimage.find_objects(labeled_Edges)[3]
>>>(slice(127, 166, None), slice(37, 71, None))

если мы используем этот фрагмент в качестве индекса в исходном массиве изображений, мы получим массив, содержащий только пиксели для этого объекта, помеченные для вашего удобства:

slices = labeled_Edges[sliced]
>>>[[4 4 4 ... 4 4 4]
   [4 4 4 ... 4 4 4]
   [4 4 4 ... 4 4 4]
   ...
   [4 4 4 ... 4 4 4]
   [4 4 4 ... 4 4 4]
   [4 4 4 ... 4 4 4]]

4 просто означает, что это четвертый помеченный объект на изображении, так как мы искали labeled_Edges[3] в этом случае.На практике вы захотите автоматизировать это, используя цикл for, с диапазоном от 1 до features, но как только вы получите свои фрагменты, у вас будут индексы для начала и остановки любого дорожного тайла, иВы просто размещаете край следующей дорожной плитки на следующем пикселе.Итак, в приведенном выше примере наши углы находятся на (127, 37), (127, 71), (166, 37), and (166,71).Размещение вашей следующей дороги может быть автоматизировано с помощью этих углов.Например, если вы хотите разместить дорожный блок справа от этого, и если вы ссылаетесь на блок, который вы размещаете, используя верхний левый угол, новая дорога будет размещена в (166, 37).Чтобы разместить тот же блок слева от этого, используя тот же угол, что и якорь, вы должны поместить его в (127 - new_block_length, 37).

К сожалению, некоторые аспекты вашего вопроса довольно неспецифичны.У вас есть места, где хранятся дорожные изображения, или вам нужно, чтобы программа действительно смотрела на изображение?Вы хотите, чтобы все возможные горизонтальные дороги размещались, когда вы нажимаете «горизонтальный», или есть метод для ссылки на конкретную дорогу?Вы размещаете дороги, используя центральный пиксель или один из углов?Есть только много переменных, которые мешают вам написать код для этого решения, но это может дать вам некоторые идеи, которые вы можете попробовать, и, по крайней мере, вы увидите, как вы локализуете объекты в самом изображении.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...