Я использую Kivy для разработки приложения для рисования n-стороннего многоугольника поверх живого видеопотока, чтобы разграничить области интереса. У меня проблема в том, что Kivy предоставляет координаты всему окну, а не только изображению. Я хотел бы, чтобы щелкнуло местоположение пикселя (в шнурах x и y). Я просмотрел метод to_local(), но он не имел особого смысла и не дал желаемых результатов. Любая помощь будет оценена по достоинству, ниже MRE.
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Color, Ellipse, Line
from random import random
class ImageView(Image):
def on_touch_down(self, touch):
##
# This provides touch cords for the entire app and not just the location of the pixel clicked#
print("Touch Cords", touch.x, touch.y)
##
color = (random(), 1, 1)
with self.canvas:
Color(*color, mode='hsv')
d = 30.
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud['line'].points += [touch.x, touch.y]
class DMSApp(App):
def build(self):
imagewidget = ImageView(source = "/home/red/Downloads/600.png")
imagewidget.size_hint = (1, .5)
imagewidget.pos_hint = {"top": 1}
layout = BoxLayout(size_hint=(1, 1))
layout.add_widget(imagewidget)
return layout
if __name__ == '__main__':
DMSApp().run()
Вы можете рассчитать координаты касания относительно левого нижнего угла фактического изображения, которое появляется в графическом интерфейсе. Затем эти координаты можно масштабировать до фактического размера исходного изображения, чтобы получить разумную оценку фактических координат пикселей в источнике. Вот модифицированная версия вашего метода in_touch_down()
, который делает это (проведено только минимальное тестирование):
def on_touch_down(self, touch):
if not self.collide_point(*touch.pos):
return super(ImageView, self).on_touch_down(touch)
lr_space = (self.width - self.norm_image_size[0]) / 2 # empty space in Image widget left and right of actual image
tb_space = (self.height - self.norm_image_size[1]) / 2 # empty space in Image widget above and below actual image
print('lr_space =', lr_space, ', tb_space =', tb_space)
print("Touch Cords", touch.x, touch.y)
print('Size of image within ImageView widget:', self.norm_image_size)
print('ImageView widget:, pos:', self.pos, ', size:', self.size)
print('image extents in x:', self.x + lr_space, self.right - lr_space)
print('image extents in y:', self.y + tb_space, self.top - tb_space)
pixel_x = touch.x - lr_space - self.x # x coordinate of touch measured from lower left of actual image
pixel_y = touch.y - tb_space - self.y # y coordinate of touch measured from lower left of actual image
if pixel_x < 0 or pixel_y < 0:
print('clicked outside of image\n')
return True
elif pixel_x > self.norm_image_size[0] or \
pixel_y > self.norm_image_size[1]:
print('clicked outside of image\n')
return True
else:
print('clicked inside image, coords:', pixel_x, pixel_y)
# scale coordinates to actual pixels of the Image source
print('actual pixel coords:',
pixel_x * self.texture_size[0] / self.norm_image_size[0],
pixel_y * self.texture_size[1] / self.norm_image_size[1], '\n')
color = (random(), 1, 1)
with self.canvas:
Color(*color, mode='hsv')
d = 30.
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y))
return True