前のセクションではカメラを読み取る方法を学びましたが、今日は opencv のマウス イベントについて学びます
1: 関連する API
Windows は、Ctrl ボタンを押しながら関連する API をクリックして、パッケージ化ページにジャンプします。API
について理解できない点がある場合は、OpenCV 公式 Web サイトに直接アクセスすることをお勧めします。ネチズンが解説しています。
1. マウスイベントを設定する
setMouseCallback(const String & winname, #要设置鼠标事件的窗口名
MouseCallback onMouse, #回调函数,当窗口产生鼠标事件时,调用的函数名
void* userdata = 0) #传递给回调函数的可选参数
2. マウスホイールの応答:
value = getMouseWheelDelta(flags); // value > 0 向上 value < 0 向下
void resize( InputArray src,
OutputArray dst,
Size dsize, //输出图像的尺寸
double fx = 0, //水平方向上的缩放系数,当fx为0时,将由公式 (double)dsize.width/src.cols 计算得到
double fy = 0, //垂直方向上的缩放系数,如果fy为0,将由公式 (double)dsize.height/src.rows 计算得到
int interpolation = INTER_LINEAR );//图像缩放的插值算法类型
3. コールバック関数のプロトタイプ
void MouseCallback(int event, #鼠标基础事件
int x, int y, #鼠标在x轴y轴方向上的坐标值,窗口左上角为原点(0,0)
int flags, #flags的值代表鼠标拖拽事件和Ctrl、Shift、Alt按键事件的代号
void *userdata) #用户数据
つまり、マウスでどのような機能を実現したいのかということです。
def mcallback(event,x,y,flags,userdata):#输出鼠标坐标
print(event,x,y,flags,userdata)
4. マウスイベント
import cv2
mouse_shijian=[i for i in dir(cv2) if 'EVENT'in i] #将全部鼠标事件保存在列表中
print (mouse_shijian) #打印列表
結果
#マウスドラッグイベントとCtrl、Shift、Altキーイベント
EVENT_FLAG_LBUTTON 1 #左キードラッグ
EVENT_FLAG_RBUTTON 2 #右キードラッグ
EVENT_FLAG_MBUTTON 4 #中キー(ローラー)ドラッグ
EVENT_FLAG_CTRLKEY 8 #(8~15)Ctrlキーを押しながらEVENT_FLAG_SHIFTKEYを押す
16 #( 16 ~31) Shift キーを押したまま
EVENT_FLAG_ALTKEY 32 #(32~39) Alt キーを押したまま#マウスの基本イベント
EVENT_MOUSEMOVE 0 #スライド
EVENT_LBUTTONDOWN 1 #左クリック
EVENT_RBUTTONDOWN 2 #右クリック
EVENT_MBUTTONDOWN 3 #中クリック
EVENT_LBUTTONUP 4 #左クリックで EVENT_RBUTTONUP を解放
5 #右クリックで
EVENT_MBUTTONUP を解放 6 #中クリックで
EVENT_LBUTTONDBLCLK を解放 7 #左ボタンダブル-クリック
EVENT_RBUTTONDBLCLK 8 #右クリック ダブルクリック
EVENT_MBUTTONDBLCLK 9 #中クリック ダブルクリック
2: コードのデモンストレーション
1. マウス座標を出力する
#python
import cv2
import numpy as np
#鼠标回调函数
def mcallback(event,x,y,flags,userdata):
print(x,y)
cv2.namedWindow('mouse', cv2.WINDOW_AUTOSIZE)
cv2.resizeWindow('mouse', 640, 480)
#设置鼠标回调
cv2.setMouseCallback('mouse',mcallback,"123")
img=np.zeros((480,640,3),np.uint8)#全黑图片
while True:
cv2.imshow('mouse',img)
key=cv2.waitKey(0)#为0则只显示一帧
if(key&0xff==ord('q')):
break
cv2.destroyAllWindows()
結果は次のとおりです
2. 画像のフレームを設定する
//C++
Point sp(-1, -1); //起始点(初始值-1,-1)
Point ep(-1, -1); //结束点(初始值-1,-1)
Mat temp; //原图的克隆,用于实时刷新图片
static void on_draw(int event, int x, int y, int flags, void* userdata) {
Mat bg = *(Mat*)userdata; //回调函数传过来的图像数据
if (event == EVENT_LBUTTONDOWN) {
//如果左键被按下
sp.x = x; //保存左键按下时的xy值
sp.y = y;
std::cout << "Start point: " << sp << std::endl;
}
else if (event == EVENT_LBUTTONUP) {
//如果左键被抬起
ep.x = x; //保存左键抬起时的xy值
ep.y = y;
int dx = ep.x - sp.x; //计算矩形长宽
int dy = ep.y - sp.y;
if (dx > 0 && dy > 0) {
//当矩形长宽都为正数时
Rect box(sp.x, sp.y, dx, dy);
temp.copyTo(bg);
rectangle(bg, box, Scalar(0, 0, 255), 2, 8, 0); //绘制矩形
imshow("Mouse Drawing", bg);
imshow("ROI", temp(box)); //显示ROI区域(被框选的区域)
sp.x = -1; //起始点坐标复位
sp.y = -1;
}
}
else if (event == EVENT_MOUSEMOVE) {
if (sp.x > 0 && sp.y > 0) {
//当起始点坐标不是初始值,且鼠标移动时
ep.x = x;
ep.y = y;
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
if (dx > 0 && dy > 0) {
Rect box(sp.x, sp.y, dx, dy);
temp.copyTo(bg); //刷新屏幕,清除上一循环绘制的矩形
rectangle(bg, box, Scalar(0, 0, 255), 2, 8, 0); //绘制新矩形
imshow("Mouse Drawing", bg);
}
}
}
}
void MyDemo::mouseDrawing_Demo(Mat& image) {
namedWindow("Mouse Drawing", WINDOW_AUTOSIZE); //创建一个窗口
setMouseCallback("Mouse Drawing", on_draw,(void*)(&image)); //调用鼠标回调函数
imshow("Mouse Drawing", image);
temp = image.clone();
}
import cv2
img_path = r"C:\Users\DMr\Pictures\text\wenben1.jpg"
def on_mouse(event, x, y, flags, param):
global img, point1, point2, cut_img
img2 = img.copy()
if event == cv2.EVENT_LBUTTONDOWN: # 左键点击
point1 = (x, y)
cv2.circle(img2, point1, 10, (0, 255, 0), 3)
cv2.imshow('image', img2)
elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): # 按住左键拖曳
cv2.rectangle(img2, point1, (x, y), (255, 0, 0), 3)
cv2.imshow('image', img2)
elif event == cv2.EVENT_LBUTTONUP: # 左键释放
point2 = (x, y)
cv2.rectangle(img2, point1, point2, (0, 255, 255), 3)
cv2.imshow('image', img2)
min_x = min(point1[0], point2[0])
min_y = min(point1[1], point2[1])
width = abs(point1[0] - point2[0])
height = abs(point1[1] - point2[1])
cut_img = img[min_y:min_y + height, min_x:min_x + width]
cv2.imshow('jietu', cut_img)
img = cv2.imread(img_path,0)
#img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
cv2.namedWindow('image')
cv2.setMouseCallback('image', on_mouse)
cv2.imshow('image', img)
key = cv2.waitKey(0) # 接收按键信息---16位
if (key & 0xff == ord('q')): # esc退出--取key的最后八位
cv2.destroyAllWindows()
else:
print(key)
cv2.destroyAllWindows()
出力
3. マウスホイールのズーム画像
//C++
static void on_Mouse(int event, int x, int y, int flags, void* userdata)
{
// 获得图像
Mat image = *(Mat*)userdata;
Mat imgzoom;
int value;
// 判断鼠标事件
if (event == EVENT_MOUSEWHEEL)
{
// 获取鼠标滚轮的方向
value = getMouseWheelDelta(flags);
if (value > 0) // 向上
{
// 放大
cout <<"h:"<<h <<" w:"<<w<< "鼠标向上";
resize(image, imgzoom,Size(h * 2,w * 2),0,0,INTER_LINEAR);
h = h * 2;
w = w * 2;
}
else if(value < 0 ) // 向下
{
cout << "h:" << h << " w:" << w << "鼠标向下";
//缩小
resize(image,imgzoom,Size(h / 2, w / 2),0,0,INTER_LINEAR);
h = h / 2;
w = w / 2;
}
if (!image.empty())
{
// 显示
imshow("缩放图像", imgzoom);;
}
}
}
void ControllSize(Mat &img)
{
namedWindow("缩放图像");
h = img.rows;
w = img.cols;
setMouseCallback("缩放图像", on_Mouse,(void*)(&img));
imshow("缩放图像",img);
}
毎日の「ビッグパイ」:
古代から、英雄は若者から生まれました。
私が 10 代だったとき、月が私を照らした日を思い出します。私のカップは氷と雪でいっぱいです。私が 10 代だったとき、私の肝臓は胆嚢
は人のせいでいつも熱かった。