2.2.4 C#中显示控件BDPictureBox 的实现----ROI交互
1 界面效果
在设定模式下,可以进行ROI 框的拖动,这里以Rect1举例说明
2 增加ROI类定义
/// <summary>
/// ROI_single
/// 用于描述图片感兴趣区域
/// type: 0:Rect1;1:Rect2;2:Circle ;3:Ellipse;4:Arc;5:Polygen;6:Point;7:line;
/// </summary>
public class ROI_single
{ // Rect1 = 0,
// Rect2 = 1,
// Circle = 2,
// Ellipse = 3,
// Arc = 4,
// Polygen = 5,
// Point = 6,
// Line = 7
public int m_nType;
// 参考labview ROIdiscriptor
public List<float> m_fDatas;
}
3 ROI生命周期示意图
4 Button_Rect1 事件
创建或者显示ROI—Rect1矩形
if (m_raw_mat != null)
{ // 更新原始图片数据
Clear_Overlay_Internal();
if (m_ROIs[m_ROI_index].m_nType != 0 || m_ROIs[m_ROI_index].m_fDatas.Count == 0)
{
// 如果主ROI 重画 ,Mask全部清空
if (m_ROI_index == 0)
{
for (int i = 1; i < 5; i++) m_ROIs[i] = new ROI();
}
m_ROIs[m_ROI_index].m_nType = 0;
m_ROIs[m_ROI_index].m_fDatas.Clear();
//一般要求图片 大于30万像素
m_ROIs[m_ROI_index].m_fDatas.Add((Single)m_raw_mat.Width / 4);
m_ROIs[m_ROI_index].m_fDatas.Add((Single)m_raw_mat.Height / 4);
m_ROIs[m_ROI_index].m_fDatas.Add((Single)3 * m_raw_mat.Width / 4);
m_ROIs[m_ROI_index].m_fDatas.Add((Single)3 * m_raw_mat.Height / 4);
}
Disp_InterActive_ROIs_without_Update_Image(m_ROIs, MainColor_Roi, n_draw_ROI_thick);
m_ROI_draw_info.draw_mode = ROIDRAWMODE.NONE;
}
5 MouseDown选中ROI
这里以ROI_Rect1为例
private void pB_Display_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && e.Clicks == 1)
{
try
{
lock (mutex_display)
{
m_MouseAction = 0;
m_pLast.X = e.X;
m_pLast.Y = e.Y;
m_pCur.X = e.X;
m_pCur.Y = e.Y;
OpenCvSharp.Point pt_img = DispManager.get_DispCTX().get_point_in_img(e.X, e.Y);
float x_img = pt_img.X;
float y_img = pt_img.Y;
if (m_ROI_index != -1)
{
if (!BD_Window_State_Judge()) return;
bd_window_state = BDDISPLAY_STATE.display_overlay;
// 进行交互画图
try
{
switch (m_ROItool_Type)
{
case 0: //none
m_MouseAction = ROI_MOUSE_ACTION.None;
break;
case ROITOOL_TYPE.PAN://pan mode
m_MouseAction = ROI_MOUSE_ACTION.DragImage;
break;
case ROITOOL_TYPE.RECT1:// rect1
//step0: 判断
if (m_ROIs[m_ROI_index].m_nType != 0 || m_ROIs[m_ROI_index].m_fDatas.Count == 0)
{
m_ROI_draw_info.draw_mode = ROIDRAWMODE.NEWDRAW;
m_ROIs[m_ROI_index].m_nType =(int)( m_ROItool_Type - 2);
m_ROIs[m_ROI_index].m_fDatas.Add((Single)x_img);
m_ROIs[m_ROI_index].m_fDatas.Add((Single)y_img);
m_ROIs[m_ROI_index].m_fDatas.Add((Single)x_img);
m_ROIs[m_ROI_index].m_fDatas.Add((Single)y_img);
Disp_InterActive_ROIs_without_Update_Image(m_ROIs, MainColor_Roi, n_draw_ROI_thick);
m_ROI_draw_info.selected_point_index = 1;// 默认第2个点
m_ROI_draw_info.draw_mode = ROIDRAWMODE.DRAGPOINT;
m_MouseAction = ROI_MOUSE_ACTION.DragROI;
break;
}
if (m_ROIs[m_ROI_index].m_nType == 0 && m_ROIs[m_ROI_index].m_fDatas.Count == 4) //rect
{
// 2.1 判断key point是否选中
m_ROI_draw_info.selected_point_index = get_interactive_key_draw_point((int)x_img, (int)y_img); ;
switch (m_ROI_draw_info.selected_point_index)
{
case 0:
m_ROI_draw_info.draw_mode = ROIDRAWMODE.DRAGPOINT;
break;
case 1:
m_ROI_draw_info.draw_mode = ROIDRAWMODE.DRAGPOINT;
break;
case 2:
m_ROI_draw_info.draw_mode = ROIDRAWMODE.SHIFTROI;
break;
case -1:
m_ROI_draw_info.draw_mode = 0;
break;
default:
m_ROI_draw_info.draw_mode = 0;
break;
}
m_MouseAction = ROI_MOUSE_ACTION.DragROI;
break;
}
break;
default:
break;
}
if (m_MouseAction == ROI_MOUSE_ACTION.DragROI)
{
Clear_Extract_Zoom_Overlay();
// 后续可以改善成 只清除局部区域
}
}
catch (Exception ex)
{
m_MouseAction = ROI_MOUSE_ACTION.None;
label_img_info.Text = "Mouse Down:" + ex.Message;
}
// 保存 old ROIs clear用
m_old_ROIs = m_ROIs;
bd_window_state = BDDISPLAY_STATE.idle;
}
}
}
catch (Exception ex)
{
m_MouseAction = ROI_MOUSE_ACTION.None;
label_img_info.Text = "Mouse Down:" + ex.Message;
}
}
}
6 MouseMove 拖动ROI
鼠标拖动ROI的某个关键点或者整体平移ROI
private void pB_Display_MouseMove(object sender, MouseEventArgs e)
{
// 2022 08 13 改善 pan img 图片很大时 迟钝 ,mouse move的频率看起来比 hscr 要快
if (m_MouseAction == ROI_MOUSE_ACTION.DragImage)
{
double t_gap = DateTime.Now.Subtract(_last_pan).TotalMilliseconds;
if (t_gap < 40) return;
}
double m_rvalue, m_gvalue, m_bvalue;
float x_img, y_img;
int nRet = 0;
try
{
if (!BD_OperateSet.MatisNotNull(m_raw_mat)) return;
lock (mutex_display)
{
if (m_MouseAction != ROI_MOUSE_ACTION.None)
{
if ((m_MouseAction != ROI_MOUSE_ACTION.DragImage && m_MouseAction != ROI_MOUSE_ACTION.DragROI) || !BD_Window_State_Judge()) return;
bd_window_state = BDDISPLAY_STATE.mouse_drag;
try
{
if (m_MouseAction != ROI_MOUSE_ACTION.WheelImage && e.Button == MouseButtons.Left)// 只有鼠标左键可以drag
{
// 只有两种情况 dragimg 或者 dragROI
if (m_MouseAction == ROI_MOUSE_ACTION.DragImage || m_MouseAction == ROI_MOUSE_ACTION.DragROI)
{
lock (mutex_display)
{
m_pCur.X = e.X;
m_pCur.Y = e.Y;
m_pDist_mouse.X = (int)(m_pCur.X - m_pLast.X);
m_pDist_mouse.Y = (int)(m_pCur.Y - m_pLast.Y);
m_pDist_img = DispManager.get_DispCTX().get_mousemove_shift_in_ccs(m_pDist_mouse);
switch (m_ROItool_Type)
{
case 0:// none
break;
case ROITOOL_TYPE.PAN:// pan
{
DispManager.get_DispCTX().update_Scroll_Info_after_pan(m_pDist_mouse);
update_ExtractRGB_and_NewOverlay();
//更新显示
Flush_Overlay_to_Display();
}
break;
default:
switch (m_ROI_draw_info.draw_mode)
{
case 0:// none
break;
case ROIDRAWMODE.NEWDRAW:// new draw
break;
case ROIDRAWMODE.DRAGPOINT: // dragon
case ROIDRAWMODE.SHIFTROI: // shift
{
Clear_InterActive_ROIs(m_old_ROIs, Black, n_draw_ROI_thick);
drag_interactive_ROI(m_pDist_img.X, m_pDist_img.Y);
Disp_InterActive_ROIs_without_Update_Image(m_ROIs, MainColor_Roi, n_draw_ROI_thick);
}
break;
default:
break;
}
break;
}
// 保存 old ROIs clear用
m_old_ROIs = m_ROIs;
}
}
// 这里更新 m_pLast 是因为 ROI 更新时 也是实时更新 ROI 的数据的
// 如果改成 Roi_last 一直不变 ,然后显示临时ROI ,这样 就可以不用更新m_pLast, 这样会更加准确
switch (m_ROItool_Type)
{
case ROITOOL_TYPE.PAN:// pan
m_pLast.X = m_pCur.X;
m_pLast.Y = m_pCur.Y;
break;
default:
m_pLast.X = m_pCur.X;
m_pLast.Y = m_pCur.Y;
break;
}
}
}
catch (Exception ex)
{
label_img_info.Text = "MouseMove:" + ex.Message;
}
bd_window_state = BDDISPLAY_STATE.idle;
}
//if (m_MouseAction == ROI_MOUSE_ACTION.None) // 空余时间 显示图像信息
else
{
// disp img info
// 参考以前代码源程序
}
}
}
catch (Exception ex)
{
label_img_info.Text = "MouseMove:" + ex.Message;
}
_last_pan = DateTime.Now;
}
6 MouseUp事件
标志位复位
m_ROI_draw_info.draw_mode = 0;
m_ROI_draw_info.selected_point_index = -1;