網站首頁 編程語言 正文
1.opencv API及參數介紹
cv::setMouseCallback(const string& windowname, MouseCallback onMouse, void* userdata=0)
{
....
}
// windowname: 要操作的窗口名稱
// onMouse: 鼠標事件函數,鼠標事件發生以后,要執行的回調函數。函數原型是
// void onMouse(int event, int x, int y, int flags, void * para)
// userdata: 回調函數的參數
鼠標回調函數介紹:
void onMouse(int event, int x, int y, int flags, void *para)
// int event: 鼠標事件,見后續說明
// x, y 是鼠標在圖像坐標系中的坐標
// flags :
// para: 是用戶傳遞到回調函數中的參數
截取感興趣區域ROI:
cv::selectROIs("MultiTracker", frame, bboxes_, showCrosshair, fromCenter);
// “MultiTracker” : windowsName
// frame: 當前畫面;格式為cv::Mat
// bboxes: 要存儲的框框格式為:std::vector<cv::Rect>
// showCrosshair:默認為True
// fromCenter:從中心點還是從對角點,默認為false,為true時,選框從中心點開始
涉及的相關參數:
// EVENT的參數定義
enum
{
CV_EVENT_MOUSEMOVE =0,//滑動
CV_EVENT_LBUTTONDOWN =1,//左鍵點擊
CV_EVENT_RBUTTONDOWN =2,//右鍵點擊
CV_EVENT_MBUTTONDOWN =3,//中鍵點擊
CV_EVENT_LBUTTONUP =4,//左鍵放開
CV_EVENT_RBUTTONUP =5,//右鍵放開
CV_EVENT_MBUTTONUP =6,//中鍵放開
CV_EVENT_LBUTTONDBLCLK =7,//左鍵雙擊
CV_EVENT_RBUTTONDBLCLK =8,//右鍵雙擊
CV_EVENT_MBUTTONDBLCLK =9//中鍵雙擊
};
enum
{
CV_EVENT_FLAG_LBUTTON =1,//左鍵拖拽
CV_EVENT_FLAG_RBUTTON =2,//右鍵拖拽
CV_EVENT_FLAG_MBUTTON =4,//中鍵拖拽
CV_EVENT_FLAG_CTRLKEY =8,//按CTRL不放
CV_EVENT_FLAG_SHIFTKEY =16,//按SHIFT不放
CV_EVENT_FLAG_ALTKEY =32//按ALT不放
};
或者python-opencv中的參數也相同:
# mouse callback function
def mouse_event(event, x, y, flags, param):
'''
:param event: 點擊事件標識
:param x: 坐標x
:param y: 坐標y
:param flags:按鍵事件標識
:param param: 攜帶參數
:return:
'''
if flags == cv2.EVENT_FLAG_ALTKEY:
print('摁住Alt')
if flags == cv2.EVENT_FLAG_CTRLKEY:
print('摁住Ctrl')
if flags == cv2.EVENT_FLAG_SHIFTKEY:
print('摁住Shift')
if flags == cv2.EVENT_FLAG_LBUTTON:
print('摁住左鍵')
if flags == cv2.EVENT_FLAG_MBUTTON:
print('摁住中鍵')
if flags == cv2.EVENT_FLAG_RBUTTON:
print('摁住右鍵')
if event == cv2.EVENT_LBUTTONDBLCLK:
print('左鍵雙擊')
if event == cv2.EVENT_MBUTTONDBLCLK:
print('中鍵雙擊')
if event == cv2.EVENT_RBUTTONDBLCLK:
print('右鍵雙擊')
if event == cv2.EVENT_LBUTTONDOWN:
print('左鍵擊下')
if event == cv2.EVENT_LBUTTONUP:
print('左鍵彈起')
if event == cv2.EVENT_MBUTTONDOWN:
print('中鍵擊下')
if event == cv2.EVENT_MBUTTONUP:
print('中鍵彈起')
if event == cv2.EVENT_RBUTTONDOWN:
print('右鍵擊下')
if event == cv2.EVENT_RBUTTONUP:
print('右鍵彈起')
if event == cv2.EVENT_MOUSEWHEEL:
if flags > 0:
print('向前滾動')
else:
print('向后滾動')
if event == cv2.EVENT_MOUSEHWHEEL:
if flags > 0:
print('向左滾動') # 按住Alt
else:
print('向右滾動')
if __name__ == '__main__':
img = np.mat(np.zeros((300, 300, 3), np.uint8)) # 構造一個像素值全為1的圖形
cv2.namedWindow('mouse') #命名窗口為mouse
cv2.setMouseCallback('mouse', mouse_event) # 窗口與回調函數綁定
while True:
cv2.imshow('mouse', img)
if cv2.waitKey(1) & 0xFF == ord('q'): # 摁下q退出
break
cv2.destroyAllWindows() #銷毀所有窗口
2.一個可以繪制矩形和控制縮放的demo
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
#define WINNAME "畫板"
struct MouseParam
{
Mat img; //用于畫好一個后顯示
Mat imgZoomBackup; //用于zoom的還原備份
Mat imgTmp; //用于實時顯示
Mat imgBackup; //清空,顯示最初的圖
Point pt1;
Point pt2;
bool mouseLflag;
float scale;
};
//繪制矩形
void draw_rectangle(Mat& img, const Point& pt1, const Point& pt2)
{
rectangle(img, pt1, pt2, Scalar(0, 255, 0), 1, 0, 0);
}
//繪制十字線:即過一點的水平、豎直線
void draw_crossline(Mat& img, const Point& pt)
{
int width = img.cols;
int height = img.rows;
cv::Point ptv1;
cv::Point ptv2;
cv::Point pth1;
cv::Point pth2;
ptv1 = cv::Point(pt.x, 0);
ptv2 = cv::Point(pt.x, height);
pth1 = cv::Point(0, pt.y);
pth2 = cv::Point(width, pt.y);
cv::line(img, ptv1, ptv2, Scalar(255, 255, 0), 1);
cv::line(img, pth1, pth2, Scalar(255, 255, 0), 1);
}
/*
* func:實現圖像繞某一點進行縮放功能
*/
void zoom(Mat& img, const Mat& srcimg, const Point& pt, const float scale)
{
int x1, y1, x2, y2;
int width, height;
width = (int)(srcimg.cols * scale / 2.0);
height = (int)(srcimg.rows * scale / 2.0);
x1 = max(pt.x - width, 0);
y1 = max(pt.y - height, 0);
x2 = min(pt.x + width, srcimg.cols);
y2 = min(pt.y + height, srcimg.rows);
Rect zoomRect(Point(x1, y1), Point(x2, y2));
img = srcimg(zoomRect).clone();
}
void on_mouse(int event, int x, int y, int flags, void* param)
{
MouseParam* par = (MouseParam*)param;
Point pt(x, y);
double value;
float step = 0.05;
if (event == EVENT_RBUTTONDOWN) //按下右鍵,重畫
{
par->img = par->imgBackup.clone();
}
else if (event == EVENT_LBUTTONDOWN) //按下左鍵
{
par->pt1 = pt;
par->pt2 = pt;
par->mouseLflag = true;
}
else if (event == EVENT_MOUSEMOVE && flags == EVENT_FLAG_LBUTTON) //按下左鍵并移動
{
par->pt2 = pt;
}
else if (event == EVENT_LBUTTONUP)//左鍵放開進行繪制矩形框
{
par->pt2 = pt;
draw_rectangle(par->img, par->pt1, par->pt2);
//par->imgZoomBackup = par->img.clone();
par->mouseLflag = false;
}
else if (event == EVENT_MOUSEMOVE) //鼠標移動將顯示十字線
{
par->pt1 = pt;
}
else if (event == EVENT_MOUSEWHEEL) //鼠標滾動
{
value = getMouseWheelDelta(flags);
if (value > 0) //滾輪向前滾動,設為縮小
par->scale += step;
else if (value < 0) //鼠標向后滾動,設為放大
par->scale -= step;
par->scale = max((float)0.3, par->scale);
par->scale = min((float)1.0, par->scale);
zoom(par->img, par->imgZoomBackup, par->pt1, par->scale);
}
}
int main()
{
//Mat img(512, 512, CV_8UC3, Scalar::all(255));
Mat img = imread("./imgs/1/L.png");
MouseParam mouseParam;
mouseParam.img = img.clone();
mouseParam.imgBackup = img.clone();
mouseParam.imgZoomBackup = img.clone();
mouseParam.mouseLflag = false;
float step = 0.05;
mouseParam.scale = 1.0;
namedWindow(WINNAME, 0);
setMouseCallback(WINNAME, on_mouse, &mouseParam);
int key;
while (1)
{
mouseParam.imgTmp = mouseParam.img.clone();
draw_crossline(mouseParam.imgTmp, mouseParam.pt1);
if (mouseParam.mouseLflag == true)
draw_rectangle(mouseParam.imgTmp, mouseParam.pt1, mouseParam.pt2);
imshow(WINNAME, mouseParam.imgTmp);
key = waitKey(40);
if (key == 27)
{
break;
}
else if (key == toascii('q'))
{
mouseParam.scale -= step;
zoom(mouseParam.img, mouseParam.imgZoomBackup, mouseParam.pt1, mouseParam.scale);
}
else if (key == toascii('e'))
{
mouseParam.scale += step;
zoom(mouseParam.img, mouseParam.imgZoomBackup, mouseParam.pt1, mouseParam.scale);
}
}
return 0;
}
3.圖象中畫點
- 對于拼接后的圖像顯示窗口,依次繪制左右圖中的對應點程序
- 右鍵刪除尚未調通
std::vector<cv::Point2f>pointsL; //依次存放左右圖中的對應點
std::vector<cv::Point2f>pointsR;
cv::Mat mask;
cv::Point2f p_;
//鼠標回調函數
void on_mouse(int event, int x, int y, int flags, void* param)
{
float cols = mask.cols/2;
int rad = 6;
if (event == cv::EVENT_LBUTTONUP || !(flags & cv::EVENT_FLAG_LBUTTON))
cv::Point2f pt = cv::Point2f(-10, -10);
else if (event == cv::EVENT_LBUTTONDOWN)
{
cv::Point2f pt(x, y);
if (pt.x>=0&&pt.x <= cols)
{
pointsL.push_back(pt);
cv::circle(mask, pt, rad, cv::Scalar(0, 255, 0), 2);
}
else {
pointsR.push_back(pt);
cv::circle(mask, pt, rad, cv::Scalar(0, 0, 255), 2);
}
//cv::circle(mask, pt, 2, cv::Scalar(0, 255, 0), 2);
cv::imshow("image", mask);
}
else if (event == cv::EVENT_RBUTTONDOWN) //按下右鍵,重畫
{
cv::Point2f pt(x, y);
if (pointsL.size()>0)
{
pointsL.pop_back();
}
else if (pointsR.size() > 0)
{
pointsR.pop_back();
}
}
std::cout << "pointsL" << std::endl;
for (int i = 0; i < pointsL.size(); ++i)
{
std::cout << pointsL[i] << std::endl;
}
std::cout << "pointsR" << std::endl;
for (int i = 0; i < pointsR.size(); ++i)
{
std::cout << pointsR[i] << std::endl;
}
}
4.opencv例程分水嶺分割中的界面應用
鼠標時間包含繪制直線的交互操作
static void help(char** argv)
{
cout << "\nThis program demonstrates the famous watershed segmentation algorithm in OpenCV: watershed()\n"
"Usage:\n" << argv[0] << " [image_name -- default is fruits.jpg]\n" << endl;
cout << "Hot keys: \n"
"\tESC - quit the program\n"
"\tr - restore the original image\n"
"\tw or SPACE - run watershed segmentation algorithm\n"
"\t\t(before running it, *roughly* mark the areas to segment on the image)\n"
"\t (before that, roughly outline several markers on the image)\n";
}
Mat markerMask, img;
Point prevPt(-1, -1);
static void onMouse(int event, int x, int y, int flags, void*)
{
if (x < 0 || x >= img.cols || y < 0 || y >= img.rows)
return;
if (event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON))
prevPt = Point(-1, -1);
else if (event == EVENT_LBUTTONDOWN)
prevPt = Point(x, y);
else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
{
Point pt(x, y);
if (prevPt.x < 0)
prevPt = pt;
line(markerMask, prevPt, pt, Scalar(12,234,12), 40, 8, 0);
line(img, prevPt, pt, Scalar(12,234,12), 40, 8, 0);
prevPt = pt;
imshow("image", img);
}
}
int main(int argc, char** argv)
{
cv::CommandLineParser parser(argc, argv, "{help h | | }{ @input | fruits.jpg | }");
if (parser.has("help"))
{
help(argv);
return 0;
}
//string filename = samples::findFile(parser.get<string>("@input"));
Mat img0 = imread("..."), imgGray;
if (img0.empty())
{
cout << "Couldn't open image ";
help(argv);
return 0;
}
help(argv);
//img0 = img0(Rect(1000, 1000, 800, 800));
namedWindow("image", WINDOW_NORMAL);
img0.copyTo(img);
cvtColor(img, markerMask, COLOR_BGR2GRAY);
cvtColor(markerMask, imgGray, COLOR_GRAY2BGR);
markerMask = Scalar::all(0);
imshow("image", img);
setMouseCallback("image", onMouse, 0);
for (;;)
{
char c = (char)waitKey(0);
if (c == 27)
break;
if (c == 'r')
{
markerMask = Scalar::all(0);
img0.copyTo(img);
namedWindow("image", WINDOW_NORMAL);
imshow("image", img);
}
if (c == 'w' || c == ' ')
{
//對繪制完成的圖像進行下一步操作
//須在鍵入相應按鍵后執行
}
}
return 0;
}
原文鏈接:https://blog.csdn.net/yohnyang/article/details/128012689
相關推薦
- 2022-03-28 Python中三種條件語句示例介紹_python
- 2023-03-23 Android進階CoordinatorLayout協調者布局實現吸頂效果_Android
- 2022-04-24 如何在Python中隱藏和加密密碼示例詳解_python
- 2022-08-14 在WPF中使用多線程更新UI_C#教程
- 2022-12-09 OpenCV?imread讀取圖片失敗的問題及解決_python
- 2022-03-14 golang實現子網掩碼和網絡位長度相互轉換
- 2022-07-14 C++實現一個簡單的線程池的示例代碼_C 語言
- 2022-10-22 Python?NumPy教程之數組的創建詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支