对话框上有两个编辑框,来确定图像显示的范围,如下图:
需要完成图像的显示,鼠标滚轮进行图像缩放操作,鼠标中键进行图像拖动操作等功能。同时还需要显示图像提取的特征结果,在缩放和拖动操作中,特征结果也需要进行相应处理。效果如下图
为实现以上要求,需要先将坐标系的关系理清,此为重点。
1、图像显示坐标系,显示图像使用。坐标系原点在左下角,向右为X轴正方向,向上为Y轴正方向
2、设备坐标系,DC画图使用,在屏幕上画出特征时,会使用到。坐标系原点在左上角,向右为X轴正方向,向下为Y轴正方向
3、像素坐标系(也可成为图像坐标系),特征提取后,得到的像素值就在此坐标系下。 坐标系原点在左上角,向右为X轴正方向,向下为Y轴正方向
此三个坐标系之间的关系,一定要弄清楚。经常需要来回转换。图像显示到指定区域,网上有很多资源,不再赘述。当显示到对话框上指定编辑框上时,注意对话框的视图坐标和编辑框的视图坐标转换。
此段代码在对话框类的mousemove消息函数中,获取的点坐标point是对话框视图下的,需要转换成编辑框视图下。此处点坐标也是在像素坐标系下。
CPoint ptInEdit = point;
CWnd *pWnd = GetDlgItem(IDC_STATIC_LEFT);
if (pWnd)
{
ClientToScreen(&ptInEdit);
pWnd->ScreenToClient(&ptInEdit);
}
无论是图像缩放还是拖动,都需要找到一个合适的矩形,从而实现将矩形内的图像显示到编辑框上。这个矩形的宽高可以通过原图像宽高和缩放因子一起来计算。矩形的中心为当前状态下鼠标在图像上的位置。需要通过鼠标在对话框的位置,转换为在编辑框视图下的位置,再转换为像素坐标系下,最后再转换为图像显示坐标系下。
注意此处最后得到的是图像显示坐标系,因为得到的矩形也是图像显示坐标系下,这样可以直接进行显示。此处容易与像素坐标系混淆。同时当对图像进行缩放操作后,再转换鼠标位置时,需要考虑到当前状态下缩放计算得到的矩形,在图像显示坐标系下的位置。这样得到的鼠标位置才是准确的。
//计算 鼠标在图像上的位置 像素坐标系下
lfptDIBOffx = (ptInEdit.x*1.0) / m_dRadioX;
lfptDIBOffy = (ptInEdit.y*1.0) / m_dRadioY;
//转为图像显示坐标系下 还要考虑图像缩放后,起点的变化
m_MousePt_DIB.x = (int)(lfptDIBOffx + 0.5) + m_rectLeftImg.left;
m_MousePt_DIB.y = m_rectLeftImg.Height() - (int)(lfptDIBOffy + 0.5) + m_rectLeftImg.top;
图像拖动时,为了达到拖动效果(拖着选中区域进行移动)。也要注意坐标系的转换,主要是Y方向。向上Y值为负(像素坐标系下),真实显示矩形应该向下(将下面的图像显示到上面来,表示拖动的效果)。
无论是缩放,还是拖动。最终会得到显示矩形。得到矩形后,就可以根据矩形的数据,来计算图像提取特征应该显示的位置。
nPosX = (pImgPt[i].m_du - m_rectLeftImg.left) * m_dRadioX;
nPoxY = (pImgPt[i].m_dv - (m_nImgHeight-m_rectLeftImg.bottom)) * m_dRadioY;
特征坐标为像素坐标系。与画图使用的设备坐标系一致。但因为使用的是图像显示坐标系下的矩形数据,所以此处依然需要转换。
以上 为个人工作期间,所感所想,比较凌乱。以后再遇到相同事情,可以作为参考。