使用python在open cv中使用鼠标事件绘制矩形或直线

时间:2022-02-01 21:23:30

I am trying to draw a straight line between two coordinates which would be obtained by clicking on the image or by mouse events. I am able to draw individual circles on clicking the mouse, but cannot figure out how to draw line between those points. When I am using this code, I can only print the start and end coordinates, not draw a line between them.

我试图在两个坐标之间画一条直线,这两个坐标可以通过点击图像或鼠标事件获得。我可以在点击鼠标的时候画出单独的圆圈,但是我不知道如何在这些点之间画线。当我使用这段代码时,我只能打印开始和结束坐标,而不能在它们之间画一条线。

import numpy as np
import cv2
import cv2.cv as cv

boxes = []

def on_mouse(event, x, y, flags, params):
    if event == cv.CV_EVENT_LBUTTONDOWN:
         print 'Start Mouse Position: '+str(x)+', '+str(y)
         sbox = [x, y]
         boxes.append(sbox)

    elif event == cv.CV_EVENT_LBUTTONUP:
        print 'End Mouse Position: '+str(x)+', '+str(y)
        ebox = [x, y]
        boxes.append(ebox)


count = 0
while(1):
    count += 1
    img = cv2.imread('img.jpg',0)
    img = cv2.blur(img, (3,3))

    cv2.namedWindow('real image')
    cv.SetMouseCallback('real image', on_mouse, 0)
    cv2.imshow('real image', img)
    if count < 50:
        if cv2.waitKey(33) == 27:
            cv2.destroyAllWindows()
            break
    elif count >= 50:
        if cv2.waitKey(0) == 27:
            cv2.destroyAllWindows()
            break
        count = 0

Somehow, I am not able to extract the coordinates outside the loop. Can someone please suggest how to draw lines or rectangles between the points I click on the image?

不知何故,我无法提取环外的坐标。有人能建议我如何在点击图片的点之间画线或矩形吗?

2 个解决方案

#1


20  

You can refer below C++ code which I used to crop image

您可以参考下面的c++代码,我曾经用来裁剪映像

#include <iostream>
#include "opencv2/opencv.hpp"
#include <stdio.h>

using namespace std;
using namespace cv;


Mat src,img,ROI;
Rect cropRect(0,0,0,0);
 Point P1(0,0);
 Point P2(0,0);

const char* winName="Crop Image";
bool clicked=false;
int i=0;
char imgName[15];


void checkBoundary(){
       //check croping rectangle exceed image boundary
       if(cropRect.width>img.cols-cropRect.x)
         cropRect.width=img.cols-cropRect.x;

       if(cropRect.height>img.rows-cropRect.y)
         cropRect.height=img.rows-cropRect.y;

        if(cropRect.x<0)
         cropRect.x=0;

       if(cropRect.y<0)
         cropRect.height=0;
}

void showImage(){
    img=src.clone();
    checkBoundary();
    if(cropRect.width>0&&cropRect.height>0){
        ROI=src(cropRect);
        imshow("cropped",ROI);
    }

    rectangle(img, cropRect, Scalar(0,255,0), 1, 8, 0 );
    imshow(winName,img);
}


void onMouse( int event, int x, int y, int f, void* ){


    switch(event){

        case  CV_EVENT_LBUTTONDOWN  :
                                        clicked=true;

                                        P1.x=x;
                                        P1.y=y;
                                        P2.x=x;
                                        P2.y=y;
                                        break;

        case  CV_EVENT_LBUTTONUP    :
                                        P2.x=x;
                                        P2.y=y;
                                        clicked=false;
                                        break;

        case  CV_EVENT_MOUSEMOVE    :
                                        if(clicked){
                                        P2.x=x;
                                        P2.y=y;
                                        }
                                        break;

        default                     :   break;


    }


    if(clicked){
     if(P1.x>P2.x){ cropRect.x=P2.x;
                       cropRect.width=P1.x-P2.x; }
        else {         cropRect.x=P1.x;
                       cropRect.width=P2.x-P1.x; }

        if(P1.y>P2.y){ cropRect.y=P2.y;
                       cropRect.height=P1.y-P2.y; }
        else {         cropRect.y=P1.y;
                       cropRect.height=P2.y-P1.y; }

    }


showImage();


}
int main()
{

    cout<<"Click and drag for Selection"<<endl<<endl;
    cout<<"------> Press 's' to save"<<endl<<endl;

    cout<<"------> Press '8' to move up"<<endl;
    cout<<"------> Press '2' to move down"<<endl;
    cout<<"------> Press '6' to move right"<<endl;
    cout<<"------> Press '4' to move left"<<endl<<endl;

    cout<<"------> Press 'w' increas top"<<endl;
    cout<<"------> Press 'x' increas bottom"<<endl;
    cout<<"------> Press 'd' increas right"<<endl;
    cout<<"------> Press 'a' increas left"<<endl<<endl;

    cout<<"------> Press 't' decrease top"<<endl;
    cout<<"------> Press 'b' decrease bottom"<<endl;
    cout<<"------> Press 'h' decrease right"<<endl;
    cout<<"------> Press 'f' decrease left"<<endl<<endl;

    cout<<"------> Press 'r' to reset"<<endl;
    cout<<"------> Press 'Esc' to quit"<<endl<<endl;


    src=imread("src.png",1);

    namedWindow(winName,WINDOW_NORMAL);
    setMouseCallback(winName,onMouse,NULL );
    imshow(winName,src);

    while(1){
    char c=waitKey();
    if(c=='s'&&ROI.data){
     sprintf(imgName,"%d.jpg",i++);
     imwrite(imgName,ROI);
     cout<<"  Saved "<<imgName<<endl;
    }
    if(c=='6') cropRect.x++;
    if(c=='4') cropRect.x--;
    if(c=='8') cropRect.y--;
    if(c=='2') cropRect.y++;

    if(c=='w') { cropRect.y--; cropRect.height++;}
    if(c=='d') cropRect.width++;
    if(c=='x') cropRect.height++;
    if(c=='a') { cropRect.x--; cropRect.width++;}

    if(c=='t') { cropRect.y++; cropRect.height--;}
    if(c=='h') cropRect.width--;
    if(c=='b') cropRect.height--;
    if(c=='f') { cropRect.x++; cropRect.width--;}

    if(c==27) break;
    if(c=='r') {cropRect.x=0;cropRect.y=0;cropRect.width=0;cropRect.height=0;}
    showImage();

    }


    return 0;
}

使用python在open cv中使用鼠标事件绘制矩形或直线

#2


6  

Here's a python implementation

这是一个python实现

    import cv2
    import cv2.cv as cv
    from time import time
    boxes = []
    def on_mouse(event, x, y, flags, params):
        # global img
        t = time()

        if event == cv.CV_EVENT_LBUTTONDOWN:
             print 'Start Mouse Position: '+str(x)+', '+str(y)
             sbox = [x, y]
             boxes.append(sbox)
             # print count
             # print sbox

        elif event == cv.CV_EVENT_LBUTTONUP:
            print 'End Mouse Position: '+str(x)+', '+str(y)
            ebox = [x, y]
            boxes.append(ebox)
            print boxes
            crop = img[boxes[-2][1]:boxes[-1][1],boxes[-2][0]:boxes[-1][0]]

            cv2.imshow('crop',crop)
            k =  cv2.waitKey(0)
            if ord('r')== k:
                cv2.imwrite('Crop'+str(t)+'.jpg',crop)
                print "Written to file"

    count = 0
    while(1):
        count += 1
        img = cv2.imread('path.img',0)
        # img = cv2.blur(img, (3,3))
        img = cv2.resize(img, None, fx = 0.25,fy = 0.25)

        cv2.namedWindow('real image')
        cv.SetMouseCallback('real image', on_mouse, 0)
        cv2.imshow('real image', img)
        if count < 50:
            if cv2.waitKey(33) == 27:
                cv2.destroyAllWindows()
                break
        elif count >= 50:
            if cv2.waitKey(0) == 27:
                cv2.destroyAllWindows()
                break
            count = 0

#1


20  

You can refer below C++ code which I used to crop image

您可以参考下面的c++代码,我曾经用来裁剪映像

#include <iostream>
#include "opencv2/opencv.hpp"
#include <stdio.h>

using namespace std;
using namespace cv;


Mat src,img,ROI;
Rect cropRect(0,0,0,0);
 Point P1(0,0);
 Point P2(0,0);

const char* winName="Crop Image";
bool clicked=false;
int i=0;
char imgName[15];


void checkBoundary(){
       //check croping rectangle exceed image boundary
       if(cropRect.width>img.cols-cropRect.x)
         cropRect.width=img.cols-cropRect.x;

       if(cropRect.height>img.rows-cropRect.y)
         cropRect.height=img.rows-cropRect.y;

        if(cropRect.x<0)
         cropRect.x=0;

       if(cropRect.y<0)
         cropRect.height=0;
}

void showImage(){
    img=src.clone();
    checkBoundary();
    if(cropRect.width>0&&cropRect.height>0){
        ROI=src(cropRect);
        imshow("cropped",ROI);
    }

    rectangle(img, cropRect, Scalar(0,255,0), 1, 8, 0 );
    imshow(winName,img);
}


void onMouse( int event, int x, int y, int f, void* ){


    switch(event){

        case  CV_EVENT_LBUTTONDOWN  :
                                        clicked=true;

                                        P1.x=x;
                                        P1.y=y;
                                        P2.x=x;
                                        P2.y=y;
                                        break;

        case  CV_EVENT_LBUTTONUP    :
                                        P2.x=x;
                                        P2.y=y;
                                        clicked=false;
                                        break;

        case  CV_EVENT_MOUSEMOVE    :
                                        if(clicked){
                                        P2.x=x;
                                        P2.y=y;
                                        }
                                        break;

        default                     :   break;


    }


    if(clicked){
     if(P1.x>P2.x){ cropRect.x=P2.x;
                       cropRect.width=P1.x-P2.x; }
        else {         cropRect.x=P1.x;
                       cropRect.width=P2.x-P1.x; }

        if(P1.y>P2.y){ cropRect.y=P2.y;
                       cropRect.height=P1.y-P2.y; }
        else {         cropRect.y=P1.y;
                       cropRect.height=P2.y-P1.y; }

    }


showImage();


}
int main()
{

    cout<<"Click and drag for Selection"<<endl<<endl;
    cout<<"------> Press 's' to save"<<endl<<endl;

    cout<<"------> Press '8' to move up"<<endl;
    cout<<"------> Press '2' to move down"<<endl;
    cout<<"------> Press '6' to move right"<<endl;
    cout<<"------> Press '4' to move left"<<endl<<endl;

    cout<<"------> Press 'w' increas top"<<endl;
    cout<<"------> Press 'x' increas bottom"<<endl;
    cout<<"------> Press 'd' increas right"<<endl;
    cout<<"------> Press 'a' increas left"<<endl<<endl;

    cout<<"------> Press 't' decrease top"<<endl;
    cout<<"------> Press 'b' decrease bottom"<<endl;
    cout<<"------> Press 'h' decrease right"<<endl;
    cout<<"------> Press 'f' decrease left"<<endl<<endl;

    cout<<"------> Press 'r' to reset"<<endl;
    cout<<"------> Press 'Esc' to quit"<<endl<<endl;


    src=imread("src.png",1);

    namedWindow(winName,WINDOW_NORMAL);
    setMouseCallback(winName,onMouse,NULL );
    imshow(winName,src);

    while(1){
    char c=waitKey();
    if(c=='s'&&ROI.data){
     sprintf(imgName,"%d.jpg",i++);
     imwrite(imgName,ROI);
     cout<<"  Saved "<<imgName<<endl;
    }
    if(c=='6') cropRect.x++;
    if(c=='4') cropRect.x--;
    if(c=='8') cropRect.y--;
    if(c=='2') cropRect.y++;

    if(c=='w') { cropRect.y--; cropRect.height++;}
    if(c=='d') cropRect.width++;
    if(c=='x') cropRect.height++;
    if(c=='a') { cropRect.x--; cropRect.width++;}

    if(c=='t') { cropRect.y++; cropRect.height--;}
    if(c=='h') cropRect.width--;
    if(c=='b') cropRect.height--;
    if(c=='f') { cropRect.x++; cropRect.width--;}

    if(c==27) break;
    if(c=='r') {cropRect.x=0;cropRect.y=0;cropRect.width=0;cropRect.height=0;}
    showImage();

    }


    return 0;
}

使用python在open cv中使用鼠标事件绘制矩形或直线

#2


6  

Here's a python implementation

这是一个python实现

    import cv2
    import cv2.cv as cv
    from time import time
    boxes = []
    def on_mouse(event, x, y, flags, params):
        # global img
        t = time()

        if event == cv.CV_EVENT_LBUTTONDOWN:
             print 'Start Mouse Position: '+str(x)+', '+str(y)
             sbox = [x, y]
             boxes.append(sbox)
             # print count
             # print sbox

        elif event == cv.CV_EVENT_LBUTTONUP:
            print 'End Mouse Position: '+str(x)+', '+str(y)
            ebox = [x, y]
            boxes.append(ebox)
            print boxes
            crop = img[boxes[-2][1]:boxes[-1][1],boxes[-2][0]:boxes[-1][0]]

            cv2.imshow('crop',crop)
            k =  cv2.waitKey(0)
            if ord('r')== k:
                cv2.imwrite('Crop'+str(t)+'.jpg',crop)
                print "Written to file"

    count = 0
    while(1):
        count += 1
        img = cv2.imread('path.img',0)
        # img = cv2.blur(img, (3,3))
        img = cv2.resize(img, None, fx = 0.25,fy = 0.25)

        cv2.namedWindow('real image')
        cv.SetMouseCallback('real image', on_mouse, 0)
        cv2.imshow('real image', img)
        if count < 50:
            if cv2.waitKey(33) == 27:
                cv2.destroyAllWindows()
                break
        elif count >= 50:
            if cv2.waitKey(0) == 27:
                cv2.destroyAllWindows()
                break
            count = 0