Kivy Image ROI Selection

266 views
Skip to first unread message

prabakar s

unread,
Jan 13, 2020, 1:03:22 AM1/13/20
to Kivy users support
I'm working on an application in which I want to load an image and select an ROI. On selection, the start and end coordinates are displayed. Using widget I'm able to get the coordinate of selection(mouse down and mouse up) of the Kivy application. But, what I exactly need is the exact coordinates of the image. Is there is any way to get the ROI of the image?. It should be like an image editor in which we have the selection tool. I have added a sample code that I have tried. 
ROI_selection.py

Elliot Garbus

unread,
Jan 13, 2020, 3:18:40 PM1/13/20
to kivy-...@googlegroups.com

I’d recommend a different approach.  There are a few things going on here that concern me.  You are creating a new Image in your mouse movement commands.

self.img = Image(source=self.img_path)

each call is instancing a new Image.

 

Here is what I would recommend.  Create a new widget that inherits from Image, lets call it ROIImage.

Use the canvas to draw your ROI box rectangle on the canvas of the widget.

Use the on_touch_down() to capture the start point

Use on_touch_move to draw the ROI box.

Use on_touch_up() to capture the size and position of the drawn box.

 

Use self.collide_point(*touch.pos) to make sure the touch is in your widget.  Use touch.grab() and use touch.grab_current in on_touch_move() to test that it is the touch you grabbed, and touch.ungrab() in on_touch_up()
 

Hope that helps.

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/ebcfe28f-572d-485d-8728-1976fcf802c1%40googlegroups.com.

 

Elliot Garbus

unread,
Jan 13, 2020, 7:10:50 PM1/13/20
to Kivy users support
I got a little carried away with some time to kill... so took a shot at your code.
I also just realized I did not answer your question....
You can read the original size of your image as texture_size, and the normalized image (that fits on the screen) as norm_image_size.
you will need to determine the x and y scale factors to scale the norm_image_size to texture_size, and then apply these same scale factors to get your image based pixel positions.

The way this code is written you can import it into another file and use ROIImage.  The code on the bottom creates a single file test.



from kivy.app import App
from kivy.uix.image import Image
from kivy.properties import ListProperty
from kivy.lang import Builder

Builder.load_string('''
<ROIImage>
canvas:
Color:
rgba: root.roi_color
Rectangle:
pos: root.start_pos
size: root.current_pos[0] - root.start_pos[0], \
root.current_pos[1] - root.start_pos[1]

''')


class ROIImage(Image):
start_pos = ListProperty([0, 0])
current_pos = ListProperty([0, 0])
roi_color = ListProperty([1, 1, 1, 0.5])

def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
touch.grab(self)
self.current_pos = self.start_pos = touch.pos
return True
return False

def on_touch_move(self, touch):
if touch.grab_current is self:
self.current_pos = touch.pos
print(f'current pos: {touch.pos}')
if (self.start_pos[0] < self.current_pos[0]) and (self.start_pos[1] < self.current_pos[1]):
print("Top Right")
self.roi_color = (100 / 255, 143 / 255, 165 / 255, 0.6)

elif (self.start_pos[0] < self.current_pos[0]) and (self.start_pos[1] > self.current_pos[1]):
print("Bottom Right")
self.roi_color = (23 / 255, 143 / 255, 54 / 255, 0.6)

elif (self.start_pos[0] > self.current_pos[0]) and (self.start_pos[1] < self.current_pos[1]):
print("Top Left")
self.roi_color = (100 / 255, 93 / 255, 65 / 255, 0.6)

elif (self.start_pos[0] > self.current_pos[0]) and (self.start_pos[1] > self.current_pos[1]):
print("Bottom Left")
self.roi_color = (100 / 255, 45 / 255, 34 / 255, 0.6)
return True
return False

def on_touch_up(self, touch):
if touch.grab_current is self :
self.current_pos = touch.pos
print(f'End pos: {touch.pos}')
return True
return False

def clear(self):
self.roi_color = (1, 1, 1, 0)


if __name__ == '__main__':
kv_test = '''
BoxLayout:
orientation: 'vertical'
ROIImage:
id: roi_image
source: 'image.jpg'
Button:
size_hint_y: None
height: dp(48)
text: 'Clear'
on_release:
roi_image.clear()
'''

class ROIIMAGEApp(App):

def build(self):
return Builder.load_string(kv_test)


ROIIMAGEApp().run()

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+unsubscribe@googlegroups.com.

roi_image.py
Reply all
Reply to author
Forward
0 new messages