使用 python 在打开的 cv 中使用鼠标事件绘制矩形或线条
Posted
技术标签:
【中文标题】使用 python 在打开的 cv 中使用鼠标事件绘制矩形或线条【英文标题】:Drawing rectangle or line using mouse events in open cv using python 【发布时间】:2014-04-04 03:41:36 【问题描述】:我试图在两个坐标之间画一条直线,这将通过单击图像或鼠标事件获得。我可以在单击鼠标时绘制单个圆圈,但无法弄清楚如何在这些点之间画线。当我使用这段代码时,我只能打印开始和结束坐标,不能在它们之间画线。
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
不知何故,我无法提取循环外的坐标。有人可以建议如何在我点击图像的点之间画线或矩形吗?
【问题讨论】:
此链接可能有帮助:docs.opencv.org/doc/tutorials/core/basic_geometric_drawing/… 【参考方案1】:你可以参考下面我用来裁剪图像的 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;
【讨论】:
【参考方案2】:这是一个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
【讨论】:
对于 python3 使用 EVENT_LBUTTONDOWN 和 EVENT_LBUTTONUP 而不是 CV_EVENT_LBUTTONDOWN 和 CV_EVENT_LBUTTONUP 对于python3
使用cv2.setMouseCallback('real image', on_mouse, 0)
;)【参考方案3】:
这是您在图像上绘制线条和矩形的完整答案
import numpy as np
import cv2
# Making The Blank Image
image = np.zeros((512,512,3))
drawing = False
ix = 0
iy = 0
# Adding Function Attached To Mouse Callback
def draw(event,x,y,flags,params):
global ix,iy,drawing
# Left Mouse Button Down Pressed
if(event==1):
drawing = True
ix = x
iy = y
if(event==0):
if(drawing==True):
#For Drawing Line
cv2.line(image,pt1=(ix,iy),pt2=(x,y),color=(255,255,255),thickness=3)
ix = x
iy = y
# For Drawing Rectangle
# cv2.rectangle(image,pt1=(ix,iy),pt2=(x,y),color=(255,255,255),thickness=3)
if(event==4):
drawing = False
# Making Window For The Image
cv2.namedWindow("Window")
# Adding Mouse CallBack Event
cv2.setMouseCallback("Window",draw)
# Starting The Loop So Image Can Be Shown
while(True):
cv2.imshow("Window",image)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
【讨论】:
也许你可以添加一些关于你的代码的解释,这样从长远来看它可能会有用。以上是关于使用 python 在打开的 cv 中使用鼠标事件绘制矩形或线条的主要内容,如果未能解决你的问题,请参考以下文章
Python-OpenCV下的窗口鼠标事件交互操作(实现鼠标移动轨迹的绘制)