csindic
csindic

Reputation: 69

Python Opencv Mouse Events in Iterated List of Images

I am itertively performing operations on a list of images (for image in directory) and need to capture mouse position upon clicking for each separate image. This is not working. I have 2 options: omit the use of cv.namedWindow()/cv.setMouseCallback() or figure out how to use them within/symbiotically with a 'for loop' iterating over images in a directory. Currently, my code is such that a black window appears alongside my images of interest. Only mouse events over that black window are captured, but I want events for the windows displaying the images to be captured.

for image in images:
    img = cv.imread(image)
    cv.namedWindow("image") 
    cv.setMouseCallback("image", click)
    ...
    cv.imshow('x',img)
    k = cv.waitKey(0) & 0xFF
    if k == 27:
        cv.destroyAllWindows()

I have tried all combinations of namedWindow and setMouseCallback in and out of the for loop and none work. Does anybody know of a solution? Thanks.

Upvotes: 2

Views: 1886

Answers (2)

Jeru Luke
Jeru Luke

Reputation: 21233

I worked on a complete example.

I had a path of images containing various formats (.png, .jpg, etc.) but only chose to loop over images of .jpg format.

For every image in the given directory, upon clicking the left mouse button the corresponding point would be printed on the console. Now you can choose to do whatever you want store them in a list, or even write to a .txt file.

Upon hitting any key other than ESC key you can iterate over to the next image. The operation stops abruptly when you hit the ESC key Here is the code:

import cv2
import numpy as np
import os

path = 'C:/Users/Desktop/Cars/'

def draw_circle(event,x,y,flags,param):
    if event == cv2.EVENT_LBUTTONDOWN:        
        cv2.circle(img, (x, y), 1, (255, 0, 0), -1)
        print('Coordinates:', x, y)

if __name__ == '__main__': 
  for f in os.listdir(path):
    if f.endswith('.jpg'):
        img = cv2.imread(path + '/' + f, 1)
        cv2.namedWindow('image')
        cv2.setMouseCallback('image', draw_circle)

        cv2.imshow('image', img)
        k = cv2.waitKey(0) & 0xFF
           if k == 27:     #--- hit ESC key to stop abruptly ---
              break

cv2.destroyAllWindows() 

Upvotes: 1

Kacperito
Kacperito

Reputation: 1367

You can set the mouse callback and then handle whatever it outputs. Precisely, you can make it call a function only if the left mouse button is pressed, just like that:

# Define the function to be called on mouse click
def on_click(event, x, y, flags, param):
    # Check if the mouse was actually clicked
    if event == cv2.EVENT_LBUTTONDOWN:
        # Do something
        cv2.destroyAllWindows()

# Show the image
cv2.imshow("image", img)

# Listen to mouse events
cv2.setMouseCallback("image", on_click)

# Wait for action
cv2.waitKey(0)

Upvotes: 1

Related Questions