Reputation: 497
I have this code in which I simply display an image using OpenCV:
import numpy as np
import cv2
class LoadImage:
def loadImage(self):
self.img=cv2.imread('photo.png')
cv2.imshow('Test',self.img)
self.pressedkey=cv2.waitKey(0)
# Wait for ESC key to exit
if self.pressedkey==27:
cv2.destroyAllWindows()
# Start of the main program here
if __name__=="__main__":
LI=LoadImage()
LI.loadImage()
Once the window displayed with the photo in it, I want to display on the console (terminal) the position of the mouse when I click over the picture. I have no idea how to perform this. Any help please?
Upvotes: 28
Views: 100355
Reputation: 79
import cv2 as cv
class UiImage():
def __init__(self, ui_name='image', param={}):
self.ui_name = ui_name
cv.namedWindow(self.ui_name)
cv.setMouseCallback(self.ui_name, lambda *args:self.on_mouse(*args), param)
def __call__(self, img, flags=cv.IMREAD_UNCHANGED):
if isinstance(img, str):
img = cv.imread(img,flags)
self.img = img
cv.imshow(self.ui_name, img)
def wait(self, delay=0):
cv.waitKey(delay) #ms
if cv.getWindowProperty(self.ui_name, cv.WND_PROP_VISIBLE):
cv.destroyWindow(self.ui_name)
def on_mouse(self,event,x,y,flags,param):
'''
MouseEventTypes:
EVENT_MOUSEMOVE
EVENT_LBUTTONDOWN
EVENT_RBUTTONDOWN
EVENT_MBUTTONDOWN
EVENT_LBUTTONUP
EVENT_RBUTTONUP
EVENT_MBUTTONUP
EVENT_LBUTTONDBLCLK
EVENT_RBUTTONDBLCLK
EVENT_MBUTTONDBLCLK
EVENT_MOUSEWHEEL
EVENT_MOUSEHWHEEL
MouseEventFlags:
EVENT_FLAG_LBUTTON
EVENT_FLAG_RBUTTON
EVENT_FLAG_MBUTTON
EVENT_FLAG_CTRLKEY
EVENT_FLAG_SHIFTKEY
EVENT_FLAG_ALTKEY
'''
print(event,x,y,flags,param)
use:
ui = UiImage(ui_name='image')
def on_mouse(event,x,y,flags,param):
def is_down(flag):
return flags & flag
if event == cv.EVENT_LBUTTONDOWN:
print('Left button down',x,y)
if is_down(cv.EVENT_FLAG_ALTKEY):
print('alt is down')
ui.on_mouse = on_mouse
img = cv.imread('./test.png',cv.IMREAD_UNCHANGED)
img = './test.png'
ui(img, flags=cv.IMREAD_UNCHANGED)
ui.wait(delay=0)
https://docs.opencv.org/4.x/d7/dfc/group__highgui.html
Upvotes: 0
Reputation: 383
If anyone wants a multi-process-based GUI for drawing points and dragging to move them, here is a single file script for same.
Upvotes: 0
Reputation: 498
Below is my implementation:
No need to store the click position, ONLY display it:
def onMouse(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
# draw circle here (etc...)
print('x = %d, y = %d'%(x, y))
cv2.setMouseCallback('WindowName', onMouse)
If you want to use the positions in other places of your code, you can use below way to obtain the coordinates:
posList = []
def onMouse(event, x, y, flags, param):
global posList
if event == cv2.EVENT_LBUTTONDOWN:
posList.append((x, y))
cv2.setMouseCallback('WindowName', onMouse)
posNp = np.array(posList) # convert to NumPy for later use
Upvotes: 15
Reputation: 1564
In case, you want to get the coordinates by hovering over the image in Python 3, you could try this:
import numpy as np
import cv2 as cv
import os
import sys
# Reduce the size of image by this number to show completely in screen
descalingFactor = 2
# mouse callback function, which will print the coordinates in console
def print_coord(event,x,y,flags,param):
if event == cv.EVENT_MOUSEMOVE:
print(f'{x*descalingFactor, y*descalingFactor}\r', end="")
img = cv.imread(cv.samples.findFile('TestImage.png'))
imgheight, imgwidth = img.shape[:2]
resizedImg = cv.resize(img,(int(imgwidth/descalingFactor), int(imgheight/descalingFactor)), interpolation = cv.INTER_AREA)
cv.namedWindow('Get Coordinates')
cv.setMouseCallback('Get Coordinates',print_coord)
cv.imshow('Get Coordinates',resizedImg)
cv.waitKey(0)
Upvotes: 0
Reputation: 6666
Here is an example mouse callback function, that captures the left button double-click
def draw_circle(event,x,y,flags,param):
global mouseX,mouseY
if event == cv2.EVENT_LBUTTONDBLCLK:
cv2.circle(img,(x,y),100,(255,0,0),-1)
mouseX,mouseY = x,y
You then need to bind that function to a window that will capture the mouse click
img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
then, in a infinite processing loop (or whatever you want)
while(1):
cv2.imshow('image',img)
k = cv2.waitKey(20) & 0xFF
if k == 27:
break
elif k == ord('a'):
print mouseX,mouseY
What Does This Code Do?
It stores the mouse position in global variables mouseX
& mouseY
every time you double click inside the black window and press the a key that will be created.
elif k == ord('a'):
print mouseX,mouseY
will print the current stored mouse click location every time you press the a button.
Code "Borrowed" from here.
Upvotes: 44
Reputation: 383
Here is class based implementation of OpenCV mouse call back for getting point on an image,
import cv2
import numpy as np
#events = [i for i in dir(cv2) if 'EVENT' in i]
#print (events)
class MousePts:
def __init__(self,windowname,img):
self.windowname = windowname
self.img1 = img.copy()
self.img = self.img1.copy()
cv2.namedWindow(windowname,cv2.WINDOW_NORMAL)
cv2.imshow(windowname,img)
self.curr_pt = []
self.point = []
def select_point(self,event,x,y,flags,param):
if event == cv2.EVENT_LBUTTONDOWN:
self.point.append([x,y])
#print(self.point)
cv2.circle(self.img,(x,y),5,(0,255,0),-1)
elif event == cv2.EVENT_MOUSEMOVE:
self.curr_pt = [x,y]
#print(self.point)
def getpt(self,count=1,img=None):
if img is not None:
self.img = img
else:
self.img = self.img1.copy()
cv2.namedWindow(self.windowname,cv2.WINDOW_NORMAL)
cv2.imshow(self.windowname,self.img)
cv2.setMouseCallback(self.windowname,self.select_point)
self.point = []
while(1):
cv2.imshow(self.windowname,self.img)
k = cv2.waitKey(20) & 0xFF
if k == 27 or len(self.point)>=count:
break
#print(self.point)
cv2.setMouseCallback(self.windowname, lambda *args : None)
#cv2.destroyAllWindows()
return self.point, self.img
if __name__=='__main__':
img = np.zeros((512,512,3), np.uint8)
windowname = 'image'
coordinateStore = MousePts(windowname,img)
pts,img = coordinateStore.getpt(3)
print(pts)
pts,img = coordinateStore.getpt(3,img)
print(pts)
cv2.imshow(windowname,img)
cv2.waitKey(0)
Upvotes: 1
Reputation: 419
You can detect mouse position clicking over a picture via performing the various mouse click events.
You just to remember one thing while performing the mouse clicks events is that, you should have to use the same window name at all places wherever you are using the cv2.imshow or cv2.namedWindow
I given the working code in answer that uses python 3.x and opencv in the following the stackoverflow post: https://stackoverflow.com/a/60445099/11493115
You can refer the above link for better explanation.
Code:
import cv2
import numpy as np
#This will display all the available mouse click events
events = [i for i in dir(cv2) if 'EVENT' in i]
print(events)
#This variable we use to store the pixel location
refPt = []
#click event function
def click_event(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
print(x,",",y)
refPt.append([x,y])
font = cv2.FONT_HERSHEY_SIMPLEX
strXY = str(x)+", "+str(y)
cv2.putText(img, strXY, (x,y), font, 0.5, (255,255,0), 2)
cv2.imshow("image", img)
if event == cv2.EVENT_RBUTTONDOWN:
blue = img[y, x, 0]
green = img[y, x, 1]
red = img[y, x, 2]
font = cv2.FONT_HERSHEY_SIMPLEX
strBGR = str(blue)+", "+str(green)+","+str(red)
cv2.putText(img, strBGR, (x,y), font, 0.5, (0,255,255), 2)
cv2.imshow("image", img)
#Here, you need to change the image name and it's path according to your directory
img = cv2.imread("D:/pictures/abc.jpg")
cv2.imshow("image", img)
#calling the mouse click event
cv2.setMouseCallback("image", click_event)
cv2.waitKey(0)
cv2.destroyAllWindows()
Upvotes: 1
Reputation: 51
import cv2
cv2.imshow("image", img)
cv2.namedWindow('image')
cv2.setMouseCallback('image', on_click)
def on_click(event, x, y, p1, p2):
if event == cv2.EVENT_LBUTTONDOWN:
cv2.circle(lastImage, (x, y), 3, (255, 0, 0), -1)
Upvotes: 5
Reputation: 1025
I have ported the PyIgnition library from Pygame to opencv2. Find the code at https://github.com/bunkahle/particlescv2 There also several examples on how to use the particle engine for Python.
Upvotes: 0