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 ROIdiscriptorpublic 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: //nonem_MouseAction = ROI_MOUSE_ACTION.None;break;case ROITOOL_TYPE.PAN://pan modem_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:// nonebreak;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:// nonebreak;case ROIDRAWMODE.NEWDRAW:// new drawbreak;case ROIDRAWMODE.DRAGPOINT: // dragoncase 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:// panm_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;