定位截图
-
说明
给出利用QImage打开图片,并设置可以任意缩放、平移功能条件下,根据绘制窗口坐标定位矩形框线,截取框线选中内容的实现。 -
核心算法
-
绘制窗口的位置和尺寸是始终固定不变,将其看作是世界坐标系。
-
图片显示在绘制窗口的子部件QLabel类型成员上,相当于绘制坐标系。图片的移动其实是该QLabel类型成员的移动。
-
最终在绘制窗口内显示的图片,是用一个临时Qimage类型变量,储存在原图的基础上进行缩放后的图片,然后将这个临时变量增加到QLabel成员上,并将QLabel成员的大小
resize
为临时QImage成员的大小,最后平移QLabel成员至绘制窗口中心。
4.经过以上描述,可知最后绘制在屏幕的图片其实是在原图基础上缩放后的图片,并经过QLabel平移呈现的。如果在绘制窗口上定位,得到的坐标其实是缩放和平移后的坐标,如果想在原图上截取定位框内的图片,需要对定位参数进行反变换,即将定位参数中的起点坐标反向平移QLabel的平移的距离,然后再将起点坐标、长和宽反向缩放图片缩放倍数(因为当前绘制坐标系显示的图片是经过先缩放后平移得到的,所以反变换应先平移后缩放),就可以得到原图上的起点坐标、长和宽。
5.完成上述操作后,得到原图上的定位参数,因为平移、缩放的系数都是小数,所得到的定位参数一般不是整数,而提取原图像素的下标应为整数, 所以应该将定位参数取整,然后判断是否越界,如果没发生越界再提取像素点。
- 源代码
//框线绘制
void THM_CT::interceptImageFrame()
{
interceptDialog* interceptD = new interceptDialog(this);
interceptD->exec();
m_interceptWidth = interceptD->width;
m_interceptHeight = interceptD->height;
m_interceptX = interceptD->x;
m_interceptY = interceptD->y;
m_interceptPattern = interceptD->pattern;
if (m_interceptPattern == false) return;
if (m_interceptX < 0 || m_interceptX > m_originalImage.width()) return;
if (m_interceptY < 0 || m_interceptY > m_originalImage.height()) return;
if (m_interceptWidth < 0 || m_interceptWidth > m_originalImage.width()) return;
if (m_interceptHeight < 0 || m_interceptHeight > m_originalImage.height()) return;
m_showFrameBoolValue = true;
update();
}
//截图
void THM_CT::interceptImage()
{
if (m_interceptPattern == false) return;
//起点坐标反变换(先平移、后缩放)
int begin_i = (m_interceptX - (m_showImageLabel->pos().x())) / m_currentIndex;
int begin_j = (m_interceptY - (m_showImageLabel->pos().y()))/ m_currentIndex;
//框线尺寸反变换(缩放)
int wid = m_interceptWidth / m_currentIndex;
int hei = m_interceptHeight / m_currentIndex;
int max_i = begin_i + wid;
int max_j = begin_j + hei;
//为了确保double转int后不越界
if (max_i - 1 > m_originalImage.width()) {
max_i = max_i - 1;
}
if (max_j - 1 > m_originalImage.height()) {
max_j = max_j - 1;
}
QImage imgTmp(wid, hei, QImage::Format_RGB16);
for (int i = begin_i; i < max_i; i++) {
for (int j = begin_j; j < max_j; j++) {
if (i >= m_originalImage.width() || j >= m_originalImage.height()) {
QMessageBox::warning(this, tr("warning"), tr("Width or height of intercept frame out of range."));
return;
}
QRgb color = m_originalImage.pixel(i, j);
imgTmp.setPixel(i - begin_i, j - begin_j, color);
}
}
imgTmp = imgTmp.scaled(m_interceptWidth, m_interceptHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
m_moveX = 0;
m_moveY = 0;
m_currentIndex = 1;
m_currentImage = imgTmp;
m_originalImage = m_currentImage;
//取消边框显示
m_showImageIncrept->clear();
m_showFrameBoolValue = false;
//显示截屏后的结果
updateImage();
}
网友评论