'Opencv: detect mouse position clicking over a picture
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?
Solution 1:[1]
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
Solution 2:[2]
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)
Solution 3:[3]
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()
Solution 4:[4]
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)
Solution 5:[5]
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.
Solution 6:[6]
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)
Solution 7:[7]
If anyone wants a multi-process-based GUI for drawing points and dragging to move them, here is a single file script for same.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | btomelleri |
| Solution 2 | Omer Meshy |
| Solution 3 | Ankit Lad |
| Solution 4 | Jerin Antony |
| Solution 5 | bunkus |
| Solution 6 | |
| Solution 7 | Jerin Antony |
