1

I am trying to show image to user and asking to click on 4 points for a rectangle from user and once user is done he will press 'c' and exit and my script should return the touch points by user.

For this approach I have written below script using OpenCV,, but not sure how to make class for this purpose iterable, might be I am wrong with some OO technical part but requirement and logic is correct because when not created inside class both functions works fine.

Code:

class mouse_select_points:
    ''' Select 4 user points from user and crop to straighten'''

    __depends__ = ['img_path']
    __provides__ = ['ratio','image_resized','click_points']

    def __init__(self, thickness=2,shape=(400,600),click_count=0,click_points=[],img_path=""):
        self.thickness = thickness
        self.shape = shape
        self.lent = click_count
        self.refPt = click_points
        self.img = img_path
        self.font = cv2.FONT_HERSHEY_SIMPLEX

    def __call__(self):
        image = cv2.imread(self.img)
        print("first loaded image size:",image.shape)
        orig_resized = image.copy()                             #create a copy of resized image
        ratio = image.shape[1] / 600.0
        self.shape = image.shape

        cv2.namedWindow("image")
        cv2.setMouseCallback("image", self._click_and_crop, param = [image] ) #setting param as image to be sent to mouse click function callback

        # keep looping until the 'c' key is pressed
        while True:
            # display the image and wait for a keypress
            cv2.imshow("image", image)
            cv2.putText(image,"press 'c' to crop or 'r' to reset",(10,15), self.font, .5,(255,255,255),1,cv2.LINE_AA)
            key = cv2.waitKey(1) & 0xFF

            # if the 'c' key is pressed, break from the loop
            elif key == ord("c") and self.lent == 4:
                break

        return ratio,orig_resized,self.refPt

    def _click_and_crop(self,event, x, y, flags, param):
        image = param[0]
        # if the left mouse button was clicked, record the starting
        # (x, y) coordinates and indicate that cropping is being performed
        if event == cv2.EVENT_LBUTTONDOWN:
            self.refPt.append([x, y])
            cv2.circle(image,(int(x),int(y)),self.thickness,(255,1,255),-1)
            self.lent += 1
            print("inside if")        
            cv2.imshow("image", image)

##testing
ratio,orig_image = mouse_select_points(img_path=r"Image1.JPG")
1
  • Can you make more clear about this: but not sure how to make class for this purpose iterable. You want to do the selection op repeatly? Or you want to return the iterable result(I think self.refPt is already iterable) ? Commented Jun 13, 2018 at 5:56

1 Answer 1

1

I think you want to pick the points repeatly. Here is it.

#!/usr/bin/python3
# 2018.06.13 13:40:12 CST
# 2018.06.13 14:17:49 CST

import cv2
class PickPoints:
    ''' Select 4 user points from user and crop to straighten'''

    __depends__ = ['img_path']
    __provides__ = ['ratio','image_resized','click_points']

    def __init__(self, thickness=2,shape=(400,600),click_count=0,click_points=[],img_path=""):
        self.thickness = thickness
        self.shape = shape
        self.lent = click_count
        self.refPt = click_points
        self.img = img_path
        self.font = cv2.FONT_HERSHEY_SIMPLEX

    def __call__(self):
        image = cv2.imread(self.img)
        #print("first loaded image size:",image.shape)
        print("="*60)
        orig_resized = image.copy()                             #create a copy of resized image
        self.shape = image.shape
        self.lent = 0
        self.refPt = []
        self.to_exit = False

        cv2.namedWindow("image")
        cv2.setMouseCallback("image", self._click_and_crop, param = [image] ) #setting param as image to be sent to mouse click function callback

        # keep looping until the 'c' key is pressed
        while True:
            # display the image and wait for a keypress
            cv2.imshow("image", image)
            cv2.putText(image,"press 'c' to crop or 'r' to reset",(10,15), self.font, .5,(255,255,255),1,cv2.LINE_AA)
            key = cv2.waitKey(30) & 0xFF
            # if the 'c' key is pressed, break from the loop
            if key == ord("r"):
                print("Reset")
                self.lent = 0
                self.refPt = []
                image[:] = orig_resized
            if key == ord("c"):
                pass
            if self.to_exit or key in (27, ord('q'), ord('Q')):
                print("Exist")
                cv2.destroyAllWindows()
                self.to_exit = False
                break

        return self.refPt

    def _click_and_crop(self,event, x, y, flags, param):
        image = param[0]
        # if the left mouse button was clicked, record the starting
        # (x, y) coordinates and indicate that cropping is being performed
        if event == cv2.EVENT_LBUTTONDOWN:
            if len(self.refPt) <4:
                self.refPt.append([x, y])
                cv2.circle(image,(int(x),int(y)),self.thickness,(0,255,0),-1)
                self.lent += 1
                print("#{} {}".format(self.lent, self.refPt[-1]))
            cv2.imshow("image", image)
        if event == cv2.EVENT_RBUTTONDOWN:
            self.to_exit = True

##testing
fname = "/home/auss/Pictures/test.png"
pk = PickPoints(img_path=fname)

print(pk())
print(pk())
print(pk())

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

I got my mistake, i was initiating and trying to call also my class at same line,, which was my bad.. Thanks for the answer..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.