如何在 OpenCV 中平移和缩放视频?
How to pan and zoom video in OpenCV?
我正在尝试使用 Python 在我的 RTSP 摄像机流中实现平移和缩放功能。我希望能够使用鼠标滚轮放大和缩小视频,然后单击并拖动来移动视频。但是,我没能找到任何关于在 OpenCV 中处理这些鼠标事件的教程。
有没有这样的方法,或者我是否必须使用击键来平移和缩放我的视频?
您可以使用鼠标事件和imshow来实现此功能。
def mouse_event_callback(self, event,x,y,flags,param):
if event == cv2.EVENT_LBUTTONDOWN:
elif event == cv2.EVENT_MOUSEMOVE:
elif event == cv2.EVENT_LBUTTONUP:
elif event == cv2.EVENT_MOUSEWHEEL:
...
cv2.namedWindow('Test')
cv2.setMouseCallback('Test',self.mouse_event_callback)
while True:
cv2.imshow('Test',img)
基本思路是决定每次鼠标滚轮改变的比例。在你得到当前比例(v.s.origin image)和你想要在屏幕上显示的正确图像区域后,你可以得到缩放图像上矩形的位置和长度。所以你可以在缩放图像上绘制这个矩形。
在我的github中,勾选Fastest_Image_Pattern_Matching/ELCVMatchTool/ELCVMatchToolDlg.cpp中的OnMouseWheel()和RefreshSrcView()应该可以给你想要的
虽然是c++代码,但是只用到了imshow()和resize()。关注我如何更改比例以及如何在缩放图像中绘制新矩形就足够了。
效果:
部分代码:
BOOL CELCVMatchToolDlg::OnMouseWheel (UINT nFlags, short zDelta, CPoint pt)
{
POINT pointCursor;
GetCursorPos (&pointCursor);
ScreenToClient (&pointCursor);
// TODO: 在此加入您的訊息處理常式程式碼和 (或) 呼叫預設值
if (zDelta > 0)
{
if (m_iScaleTimes == MAX_SCALE_TIMES)
return TRUE;
else
m_iScaleTimes++;
}
if (zDelta < 0)
{
if (m_iScaleTimes == MIN_SCALE_TIMES)
return TRUE;
else
m_iScaleTimes--;
}
CRect rect;
//GetWindowRect (rect);
GetDlgItem (IDC_STATIC_SRC_VIEW)->GetWindowRect (rect);//重要
if (m_iScaleTimes == 0)
g_dCompensationX = g_dCompensationY = 0;
int iMouseOffsetX = pt.x - (rect.left + 1);
int iMouseOffsetY = pt.y - (rect.top + 1);
double dPixelX = (m_hScrollBar.GetScrollPos () + iMouseOffsetX + g_dCompensationX) / m_dNewScale;
double dPixelY = (m_vScrollBar.GetScrollPos () + iMouseOffsetY + g_dCompensationY) / m_dNewScale;
m_dNewScale = m_dSrcScale * pow (SCALE_RATIO, m_iScaleTimes);
if (m_iScaleTimes != 0)
{
int iWidth = m_matSrc.cols;
int iHeight = m_matSrc.rows;
m_hScrollBar.SetScrollRange (0, int (m_dNewScale * iWidth - m_dSrcScale * iWidth) - 1 + BAR_SIZE);
m_vScrollBar.SetScrollRange (0, int (m_dNewScale * iHeight - m_dSrcScale * iHeight) - 1 + BAR_SIZE);
int iBarPosX = int (dPixelX * m_dNewScale - iMouseOffsetX + 0.5);
m_hScrollBar.SetScrollPos (iBarPosX);
m_hScrollBar.ShowWindow (SW_SHOW);
g_dCompensationX = -iBarPosX + (dPixelX * m_dNewScale - iMouseOffsetX);
int iBarPosY = int (dPixelY * m_dNewScale - iMouseOffsetY + 0.5);
m_vScrollBar.SetScrollPos (iBarPosY);
m_vScrollBar.ShowWindow (SW_SHOW);
g_dCompensationY = -iBarPosY + (dPixelY * m_dNewScale - iMouseOffsetY);
//滑塊大小
SCROLLINFO infoH;
infoH.cbSize = sizeof (SCROLLINFO);
infoH.fMask = SIF_PAGE;
infoH.nPage = BAR_SIZE;
m_hScrollBar.SetScrollInfo (&infoH);
SCROLLINFO infoV;
infoV.cbSize = sizeof (SCROLLINFO);
infoV.fMask = SIF_PAGE;
infoV.nPage = BAR_SIZE;
m_vScrollBar.SetScrollInfo (&infoV);
//滑塊大小
}
else
{
m_hScrollBar.SetScrollPos (0);
m_hScrollBar.ShowWindow (SW_HIDE);
m_vScrollBar.SetScrollPos (0);
m_vScrollBar.ShowWindow (SW_HIDE);
}
RefreshSrcView ();
return CDialogEx::OnMouseWheel (nFlags, zDelta, pt);
}
我正在尝试使用 Python 在我的 RTSP 摄像机流中实现平移和缩放功能。我希望能够使用鼠标滚轮放大和缩小视频,然后单击并拖动来移动视频。但是,我没能找到任何关于在 OpenCV 中处理这些鼠标事件的教程。
有没有这样的方法,或者我是否必须使用击键来平移和缩放我的视频?
您可以使用鼠标事件和imshow来实现此功能。
def mouse_event_callback(self, event,x,y,flags,param):
if event == cv2.EVENT_LBUTTONDOWN:
elif event == cv2.EVENT_MOUSEMOVE:
elif event == cv2.EVENT_LBUTTONUP:
elif event == cv2.EVENT_MOUSEWHEEL:
...
cv2.namedWindow('Test')
cv2.setMouseCallback('Test',self.mouse_event_callback)
while True:
cv2.imshow('Test',img)
基本思路是决定每次鼠标滚轮改变的比例。在你得到当前比例(v.s.origin image)和你想要在屏幕上显示的正确图像区域后,你可以得到缩放图像上矩形的位置和长度。所以你可以在缩放图像上绘制这个矩形。
在我的github中,勾选Fastest_Image_Pattern_Matching/ELCVMatchTool/ELCVMatchToolDlg.cpp中的OnMouseWheel()和RefreshSrcView()应该可以给你想要的
虽然是c++代码,但是只用到了imshow()和resize()。关注我如何更改比例以及如何在缩放图像中绘制新矩形就足够了。
效果:
部分代码:
BOOL CELCVMatchToolDlg::OnMouseWheel (UINT nFlags, short zDelta, CPoint pt)
{
POINT pointCursor;
GetCursorPos (&pointCursor);
ScreenToClient (&pointCursor);
// TODO: 在此加入您的訊息處理常式程式碼和 (或) 呼叫預設值
if (zDelta > 0)
{
if (m_iScaleTimes == MAX_SCALE_TIMES)
return TRUE;
else
m_iScaleTimes++;
}
if (zDelta < 0)
{
if (m_iScaleTimes == MIN_SCALE_TIMES)
return TRUE;
else
m_iScaleTimes--;
}
CRect rect;
//GetWindowRect (rect);
GetDlgItem (IDC_STATIC_SRC_VIEW)->GetWindowRect (rect);//重要
if (m_iScaleTimes == 0)
g_dCompensationX = g_dCompensationY = 0;
int iMouseOffsetX = pt.x - (rect.left + 1);
int iMouseOffsetY = pt.y - (rect.top + 1);
double dPixelX = (m_hScrollBar.GetScrollPos () + iMouseOffsetX + g_dCompensationX) / m_dNewScale;
double dPixelY = (m_vScrollBar.GetScrollPos () + iMouseOffsetY + g_dCompensationY) / m_dNewScale;
m_dNewScale = m_dSrcScale * pow (SCALE_RATIO, m_iScaleTimes);
if (m_iScaleTimes != 0)
{
int iWidth = m_matSrc.cols;
int iHeight = m_matSrc.rows;
m_hScrollBar.SetScrollRange (0, int (m_dNewScale * iWidth - m_dSrcScale * iWidth) - 1 + BAR_SIZE);
m_vScrollBar.SetScrollRange (0, int (m_dNewScale * iHeight - m_dSrcScale * iHeight) - 1 + BAR_SIZE);
int iBarPosX = int (dPixelX * m_dNewScale - iMouseOffsetX + 0.5);
m_hScrollBar.SetScrollPos (iBarPosX);
m_hScrollBar.ShowWindow (SW_SHOW);
g_dCompensationX = -iBarPosX + (dPixelX * m_dNewScale - iMouseOffsetX);
int iBarPosY = int (dPixelY * m_dNewScale - iMouseOffsetY + 0.5);
m_vScrollBar.SetScrollPos (iBarPosY);
m_vScrollBar.ShowWindow (SW_SHOW);
g_dCompensationY = -iBarPosY + (dPixelY * m_dNewScale - iMouseOffsetY);
//滑塊大小
SCROLLINFO infoH;
infoH.cbSize = sizeof (SCROLLINFO);
infoH.fMask = SIF_PAGE;
infoH.nPage = BAR_SIZE;
m_hScrollBar.SetScrollInfo (&infoH);
SCROLLINFO infoV;
infoV.cbSize = sizeof (SCROLLINFO);
infoV.fMask = SIF_PAGE;
infoV.nPage = BAR_SIZE;
m_vScrollBar.SetScrollInfo (&infoV);
//滑塊大小
}
else
{
m_hScrollBar.SetScrollPos (0);
m_hScrollBar.ShowWindow (SW_HIDE);
m_vScrollBar.SetScrollPos (0);
m_vScrollBar.ShowWindow (SW_HIDE);
}
RefreshSrcView ();
return CDialogEx::OnMouseWheel (nFlags, zDelta, pt);
}