You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5617 lines
129 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// ImgShowDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "ImgShowDlg.h"
#include "GlobalFunc.h"
#include "QB_ImgProcessFun.h"
#include "CvvImage.h"
#include "Markup.h"
// tif 图像
#include <ogr_srs_api.h>
#include <ogr_spatialref.h>
#include <gdal.h>
#include <gdal_priv.h>
// 文字编辑窗口
#include "AddTextDlg.h"
#include "MapPrj.h"
/*#include "GoogleTileOperation.h"*/
#include "TgtLocCalibrateDlg.h"
// CImgShowDlg 对话框
IMPLEMENT_DYNAMIC(CImgShowDlg, CDialog)
CImgShowDlg::CImgShowDlg(CWnd* pParent /*=NULL*/): CDialog(CImgShowDlg::IDD, pParent)
{
m_lpSendCoordinate = NULL;
m_lpSendPixInfoProc = NULL;
m_lpSendFilePath = NULL;
m_lpSendTgrLocLeadLonLat = NULL;
m_lpSendArtilleryReviseInfo = NULL;
m_ShowRegion = CRect(0,0,0,0);
m_ShowRegionOnScreen.left = 0;
m_ShowRegionOnScreen.right = 0;
m_ShowRegionOnScreen.top = 0;
m_ShowRegionOnScreen.bottom = 0;
m_PicCtrlWidth = 0;
m_PicCtrlHeight = 0;
m_LButtonDownPixelCoordinate = CPoint(0,0);
m_bStaisfyRoamImg = FALSE;
m_LatestPlotRect = CRect(0,0,0,0);
m_LButtonDblClkPixelCoordinate = CPoint(-1, -1);
m_bPlotRectOnPaint = TRUE;
m_NorthDirectionCenter.x = 0;
m_NorthDirectionCenter.y = 0;
m_bPlotDirectionOnPaint = TRUE;
m_LeftButtonDown.x = 0;
m_LeftButtonDown.y = 0;
m_RButtonPt.x = 0;
m_RButtonPt.y = 0;
m_SrcFrame = NULL;
m_ImgRatioOnScreen = 1.0F;
m_ImgShowShift.x = 0L;
m_ImgShowShift.y = 0L;
m_bFirstSignal = FALSE;
m_bSecondSignal = FALSE;
m_bSatisfyMove = FALSE;
m_iLatest = 0;
m_iPreLatest = 0;
m_bMemPreMultiFrame = FALSE;
m_LatestQuadrangle = CRect(0,0,0,0);
// 像素信息
m_imgPixel_XY_Coordinate.x = -1;
m_imgPixel_XY_Coordinate.y = -1;
m_imgPixel_LBH_Coordinate.x = -200.0;
m_imgPixel_LBH_Coordinate.y = -200.0;
m_imgPixel_LBH_Coordinate.z = -200.0;
m_bPlotRect = FALSE;
// 当前显示的图像序号
m_currentImgOrder = 0;
// 图像编辑类型
m_iImgEditType = 0;
m_bHaveOnPt = false;
m_bEnhanceEdit = true; // 增强
m_pFastLookUpDlg = NULL;
m_sSaveCurrentImgFolder = "";
m_sSavePreMultiImgFolder = "";
m_TargetCenter = cv::Point(-100, -100);
m_bDrawSquareOnImg = TRUE;
m_deltaLon = 0;
m_deltaLat = 0;
m_bCloseRughtBtnMenu = false;
m_sThemeText = "";
m_bGetTgtImgOn = false;
m_clipImgFirstPt = CPoint(0,0);
m_clipImgSecondPt = CPoint(0,0);
m_haveValidFirstPt = false;
// 图像裁剪开关
m_bClipImgOn = false;
m_hMutex_ProcessData = nullptr;
}
CImgShowDlg::~CImgShowDlg()
{
try
{
// 如果有图像 需要释放该图像
if (m_SrcFrame != NULL)
{
cvReleaseImage(&m_SrcFrame);
m_SrcFrame = NULL;
}
// 当前情报数据结构体:LatestQBData
ReleaseQBData(&m_LatestQBData);
WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
// 情报队列销毁
if(m_QBDataDeque.size() > 0)
{
for (size_t i = 0; i < m_QBDataDeque.size(); ++i)
{
SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.srcImg.buff);
SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.dstImg.buff);
SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.geoImg.buff);
}
m_QBDataDeque.clear();
}
ReleaseMutex(m_hMutex_ProcessData);
// midImg 释放
SAFE_DELETE_ARRAY(m_midImg.buff);
// 释放快速查找图像对话框
if (m_pFastLookUpDlg != NULL)
{
delete m_pFastLookUpDlg;
m_pFastLookUpDlg = NULL;
}
}
catch(cv::Exception &e)
{
e.what();
std::abort();
}
catch(...)
{
std::abort();
}
}
void CImgShowDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CImgShowDlg, CDialog)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_ZOOM_IN_IMG, &CImgShowDlg::OnZoomInImg)
ON_COMMAND(ID_ZOOM_OUT_IMG, &CImgShowDlg::OnZoomOutImg)
ON_COMMAND(ID_ZOOM_FIT_IMG, &CImgShowDlg::OnZoomFitImg)
ON_COMMAND(ID_CONCEL_TARGET_PLOT, &CImgShowDlg::OnConcelTargetPlot)
ON_COMMAND(ID_SAVE_CURRENT_FRAME, &CImgShowDlg::OnSaveCurrentFrame)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEWHEEL()
ON_COMMAND(ID_CLEAR_MEMORY, &CImgShowDlg::OnClearMemory)
ON_COMMAND(ID_SAVE_IMG_TO_TIFF, &CImgShowDlg::OnSaveImgToTiff)
ON_COMMAND(ID_FAST_LOOKUP_IMGS, &CImgShowDlg::OnFastLookupImgs)
ON_COMMAND(ID_TGT_LOC_LEAD, &CImgShowDlg::OnTgtLocLead)
ON_COMMAND(ID_GEO_CORRECT_AND_SHOW, &CImgShowDlg::OnGeoCorrectAndShow)
ON_COMMAND(ID_DRAW_SQUARE_ON_IMG, &CImgShowDlg::OnDrawSqureOnImg)
ON_COMMAND(ID_OPEN_ONE_IMG, &CImgShowDlg::OnOpenOneImg)
ON_COMMAND(ID_TGTLOC_calibrate, &CImgShowDlg::OnTgtloccalibrate)
ON_COMMAND(ID_VIEW_DELTA_LON_LAT, &CImgShowDlg::OnViewDeltaLonLat)
ON_COMMAND(ID_GET_TARGET_IMG, &CImgShowDlg::OnGetTargetImg)
ON_COMMAND(ID_CLIP_IMG, &CImgShowDlg::OnClipImg)
END_MESSAGE_MAP()
// 1.1 功能:设置回调函数
BOOL CImgShowDlg::SetCallBackFun(SendCoordinateProc proc)
{
// 输入数据有效性判断
if (proc != NULL)
{
m_lpSendCoordinate = proc;
return TRUE;
}
return FALSE;
}
// 2 功能设置回调函数像素信息传递到外部CSU中
// 输入:
// 1.proc: 函数指针
//
// 输出: 设置成功返回TRUE否则返回FALSE
BOOL CImgShowDlg::SetCallBackFun(SendPixInfoProc proc)
{
// 输入数据有效性判断
if (proc != NULL)
{
m_lpSendPixInfoProc = proc;
return TRUE;
}
return FALSE;
}
// 3 功能设置回调函数传递保存文件路径到外部CSU中
// 输入:
// 1.proc: 函数指针
//
// 输出: 设置成功返回TRUE否则返回FALSE
BOOL CImgShowDlg::SetCallBackFun(SendFilePath proc)
{
// 输入数据有效性判断
if (proc != NULL)
{
m_lpSendFilePath = proc;
return TRUE;
}
return FALSE;
}
BOOL CImgShowDlg::SetCallBackFun(SendTgrLocLeadLonLatProc proc)
{
// 输入数据有效性判断
if (proc != NULL)
{
m_lpSendTgrLocLeadLonLat = proc;
return TRUE;
}
return FALSE;
}
// 功能设置回调函数目标定位导引经纬度到外部CSU中
// 输入:
// 1.proc: 函数指针
//
// 输出: 设置成功返回TRUE否则返回FALSE
BOOL CImgShowDlg::SetCallBackFun(SendArtilleryReviseInfoProc proc)
{
// 输入数据有效性判断
if (proc != NULL)
{
m_lpSendArtilleryReviseInfo = proc;
return TRUE;
}
return FALSE;
}
// 1.2 功能:在对话框中显示一帧图像
BOOL CImgShowDlg::ShowOneImage(const BITMAPINFO* pImgInfo,
BYTE* pImgData,
BOOL isNeedClip,
const CRect &ShowRegion,
BOOL isNeedFlip,
float StrecthRatio,
POINT xyShift)
{
BOOL ret = FALSE;
try
{
// 数据有效性判断
if ( (pImgInfo == NULL) || (pImgData == NULL) )
{
return FALSE;
}
// 图像显示拉伸比例 有效性判定和修正
if ((StrecthRatio < 0.0F) || (StrecthRatio > 1.0F))
{
StrecthRatio = 1.0F;
}
// 图像属性提取
int imgWidth = static_cast<int>(pImgInfo->bmiHeader.biWidth);
int imgHeight = static_cast<int>(pImgInfo->bmiHeader.biHeight);
int nBitCount = static_cast<int>(pImgInfo->bmiHeader.biBitCount);
// 图像属性判断
if ( (imgWidth <= 0) || (imgHeight <= 0) )
{
return FALSE;
}
// 步长每行像素所占字节数必须扩展成4的倍数
int lineByte = (imgWidth * nBitCount / 8 + 3) / 4 * 4;
// 位图数据缓冲区的大小,即图像大小
unsigned int imgBufSize = static_cast<unsigned int>(imgHeight * lineByte);
// 将图像数据转换到 m_SrcFrame 再显示
if (m_SrcFrame != NULL) // 如果有图像
{
// 情况1如果图像属性没有变化 直接更换原始图像数据即可,即复制图像数据,不需要再去创建一幅图像
// 情况2如果图像属性发生了变化需要先释放图像再创建图像
// 情况1
if ((m_SrcFrame->width == imgWidth) &&
(m_SrcFrame->height == imgHeight) &&
(m_SrcFrame->depth * m_SrcFrame->nChannels == nBitCount) )
{
// 内存复制机制
int RealLineByte = (imgWidth * nBitCount / 8);
if (RealLineByte == lineByte)
{
memcpy(m_SrcFrame->imageData, pImgData, imgBufSize); // 图像数据复制
}
else
{
for (int i = 0; i < imgHeight; i++)
{
memcpy(m_SrcFrame->imageData + i * lineByte, pImgData + i * RealLineByte, RealLineByte);
}
}
}
else // 情况2
{
// 释放图像
cvReleaseImage(&m_SrcFrame);
m_SrcFrame = NULL;
// 创建
m_SrcFrame = cvCreateImage(cvSize(imgWidth, imgHeight), 8, nBitCount/8); // 创建图像
if (m_SrcFrame != NULL) // 创建成功
{
// 内存复制机制
int RealLineByte = (imgWidth * nBitCount / 8);
if (RealLineByte == lineByte)
{
memcpy(m_SrcFrame->imageData, pImgData, imgBufSize); // 图像数据复制
}
else
{
for (int i = 0; i < imgHeight; i++)
{
memcpy(m_SrcFrame->imageData + i * lineByte, pImgData + i * RealLineByte, RealLineByte);
}
}
}
else
{
return FALSE;
}
}
}
else // 如果没有图像 需要先创建图像
{
m_SrcFrame = cvCreateImage(cvSize(imgWidth, imgHeight), 8, nBitCount/8); // 创建图像
if (m_SrcFrame != NULL) // 创建成功
{
// 内存复制机制
int RealLineByte = (imgWidth * nBitCount / 8);
if (RealLineByte == lineByte)
{
memcpy(m_SrcFrame->imageData, pImgData, imgBufSize); // 图像数据复制
}
else
{
for (int i = 0; i < imgHeight; i++)
{
memcpy(m_SrcFrame->imageData + i * lineByte, pImgData + i * RealLineByte, RealLineByte);
}
}
}
else
{
return FALSE;
}
}
// 如果需要反转 把 SrcFrame 反转 后面的函数就再也不用考虑反转的问题
if (isNeedFlip == TRUE)
{
cvFlip(m_SrcFrame); // 上下反转,改变自身
}
// 保存图像显示属性,如果该值不合理,会在随后的重载图像显示函数中被修改
this->m_ShowRegion = ShowRegion;
// 设置图像显示拉伸系数
if (StrecthRatio >= 0.0F && StrecthRatio <= 1.0F)
{
m_ImgRatioOnScreen = StrecthRatio;
}
else
{
m_ImgRatioOnScreen = 1.0F;
}
// 转到函数1.3(重载)进行图像显示
ret = ShowOneImage(m_SrcFrame, isNeedClip, ShowRegion, m_ImgRatioOnScreen, xyShift);
return ret;
}
catch(cv::Exception &e)
{
e.msg;
return FALSE;
}
catch(...)
{
return FALSE;
}
}
// 1.3 功能:在对话框中显示一帧图像
BOOL CImgShowDlg::ShowOneImage(const IplImage* src,
BOOL isNeedClip,
const CRect &ShowRegion,
float StrecthRatio,
POINT xyShift)
{
BOOL ret = FALSE; // 返回值
try
{
// 图像数据有效性判断
if (src == NULL)
{
return FALSE;
}
// 定义变量,用于标识是否显示整个图像
// 原因:即使 isNeedClip 设置为TUREShowRegion不合理时也要显示整个图像
BOOL ShowWholeImg = TRUE;
// 判断是否需要裁剪
if (isNeedClip == TRUE) // 如果需要裁剪
{
// 判断 ShowRegion 是否合理
// 如果 ShowRegion 出现任何不合理,则显示整个图像
if ((ShowRegion.left >= 0) && (ShowRegion.left < src->width) &&
(ShowRegion.right >= 0) && (ShowRegion.right < src->width) &&
(ShowRegion.top >= 0) && (ShowRegion.top < src->height) &&
(ShowRegion.bottom >= 0) && (ShowRegion.bottom < src->height) &&
(ShowRegion.right - ShowRegion.left > 0) && (ShowRegion.bottom - ShowRegion.top > 0) )
{
// 特殊情况:裁剪整个图像
if ((ShowRegion.right - ShowRegion.left + 1 == src->width) &&
(ShowRegion.bottom - ShowRegion.top + 1 == src->height))
{
ShowWholeImg = TRUE;
}
else
{
ShowWholeImg = FALSE;
}
}
else
{
// 显示区域设置不合理,显示全部图像
ShowWholeImg = TRUE;
}
}
// 判断是否需要显示整个图像
if (ShowWholeImg == TRUE) // 如果显示整个图像
{
// 显示整个图像
ret = ShowWholeImage(src, StrecthRatio, xyShift);
// 更新图像显示区域 m_ShowRegion
// 目的:用于图像放大缩小等操作
this->m_ShowRegion.left = 0;
this->m_ShowRegion.right = src->width - 1;
this->m_ShowRegion.top = 0;
this->m_ShowRegion.bottom = src->height - 1;
}
else
{
// 裁剪出显示区域
IplImage* validPart = NULL;
// 这时ShowRegion肯定是有效的可以直接创建图像
validPart = cvCreateImage(cvSize(ShowRegion.Width(), ShowRegion.Height()), src->depth, src->nChannels);
if (validPart != NULL) // 创建成功
{
cvZero(validPart); // 清零
// 设置 感兴趣区
cvSetImageROI( const_cast<IplImage*>(src), cvRect( static_cast<int>(ShowRegion.left), static_cast<int>(ShowRegion.top), ShowRegion.Width(), ShowRegion.Height()) );
// 叠加
cvAdd( src, validPart, validPart, NULL );
// 释放 感兴趣区
cvResetImageROI( const_cast<IplImage*>(src) );
// 显示图像 validPart
ret = ShowWholeImage(validPart, StrecthRatio, xyShift);
// 释放 validPart
cvReleaseImage(&validPart);
validPart = NULL;
}
else
{
return FALSE;
}
}
return ret;
}
catch(cv::Exception &e)
{
e.msg;
return FALSE;
}
catch(...)
{
return FALSE;
}
}
// 1.4 功能:在对话框中显示一帧图像
BOOL CImgShowDlg::ShowWholeImage(const IplImage* src, float StrecthRatio, POINT &shift)
{
try
{
// 数据有效性判断
if (src == NULL)
{
return FALSE;
}
// 图像显示拉伸比例 有效性判定和修正
if ((abs(StrecthRatio) <= 0.0F) || (StrecthRatio > 1.0F))
{
StrecthRatio = 1.0F;
}
// 计算当前显示图像对话框尺寸
CRect clientRect;
GetClientRect(&clientRect);
// 获得 pictrue 控件窗口的句柄
CWnd *pWnd = NULL;
pWnd = GetDlgItem(IDC_IMG_SHOW_PIC_CTRL);
// 后面程序无需再判定
if (pWnd == NULL)
{
return FALSE;
}
// 让图像控件填满对话框
pWnd->MoveWindow(&clientRect);
// 设置图像控件尺寸
m_PicCtrlWidth = clientRect.Width(); // 图像控件宽
m_PicCtrlHeight = clientRect.Height(); // 图像控件高
// 获取图像控件HDC
CDC *pDC = NULL; // 函数退出时需要释放 ReleaseDC(pDC);
pDC = pWnd->GetDC();
// 后面程序无需再判定
if (pDC == NULL)
{
return FALSE;
}
HDC hdc = NULL;
hdc = pDC->GetSafeHdc();
// 当前图像尺寸
int imgWidth = src->width;
int imgHeight = src->height;
// 显示图像
IplImage* fitSizeImg = NULL;
// 显示图像尺寸
int fitSizeImgWidth = 0;
int fitSizeImgHeight = 0;
// 图像尺寸小于窗口尺寸
if ((imgWidth <= m_PicCtrlWidth) && (imgHeight <= m_PicCtrlHeight))
{
// 拉伸图像
double Ratio = 1.0;
double Ratio_Width = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(imgWidth);
double Ratio_Height = static_cast<double>(m_PicCtrlHeight) / static_cast<double>(imgHeight);
Ratio = (Ratio_Width < Ratio_Height) ? Ratio_Width : Ratio_Height; // Ratio 大于 1
// 拉伸比例控制
Ratio *= StrecthRatio;
// 显示图像尺寸
fitSizeImgWidth = static_cast<int>(imgWidth * Ratio + 0.5);
fitSizeImgHeight = static_cast<int>(imgHeight * Ratio + 0.5);
}
else
{
// 压缩图像
double Ratio = 1.0;
double Ratio_Img = static_cast<double>(imgWidth) / static_cast<double>(imgHeight);
double Ratio_ClientRect = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(m_PicCtrlHeight);
// 计算比例系数
if ( Ratio_Img > Ratio_ClientRect )
{
Ratio = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(imgWidth); // Ratio 小于 1
}
else
{
Ratio = static_cast<double>(m_PicCtrlHeight) / static_cast<double>(imgHeight); // Ratio 小于 1
}
// 拉伸比例控制
Ratio *= StrecthRatio;
// 显示图像尺寸
fitSizeImgWidth = static_cast<int>(imgWidth * Ratio + 0.5);
fitSizeImgHeight = static_cast<int>(imgHeight * Ratio + 0.5);
}
// 最低尺寸判断,小于一个像素时直接返回
if(min(fitSizeImgWidth, fitSizeImgHeight) <= 1)
{
// 释放
ReleaseDC(pDC);
return FALSE;
}
// 创建fitSizeImg
fitSizeImg = cvCreateImage(cvSize(fitSizeImgWidth, fitSizeImgHeight), src->depth, src->nChannels);
if (fitSizeImg == NULL)
{
return FALSE;
}
// 改变图像尺寸
cvResize(src, fitSizeImg);
// 为使显示界面不闪烁 增加中间变量 边界充满黑色
IplImage* fillblackImg = NULL;
fillblackImg = cvCreateImage(cvSize(clientRect.Width(), clientRect.Height()), src->depth, src->nChannels);
if (fillblackImg != NULL)
{
cvZero(fillblackImg); // 清零
}
else
{
// 释放缩放后图像
cvReleaseImage(&fitSizeImg);
fitSizeImg = NULL;
// 释放pdc
ReleaseDC(pDC);
return FALSE;
}
// 叠加 fitSizeImg 图像 到 fillblackImg
// 左上 起始点
cv::Point LeftUpBefore;
LeftUpBefore.x = static_cast<int>((m_PicCtrlWidth - fitSizeImgWidth)/2);
LeftUpBefore.y = static_cast<int>((m_PicCtrlHeight - fitSizeImgHeight)/2);
// 加上偏移量之后
cv::Point LeftUpAfter = LeftUpBefore;
LeftUpBefore.x += shift.x;
LeftUpBefore.y += shift.y;
// 修改全局变量 设计的不好
if (LeftUpAfter.x < 0)
{
LeftUpAfter.x = 0;
}
if (LeftUpAfter.x > m_PicCtrlWidth - fitSizeImgWidth)
{
LeftUpAfter.x = m_PicCtrlWidth - fitSizeImgWidth;
}
if (LeftUpAfter.y < 0)
{
LeftUpAfter.y = 0;
}
if (LeftUpAfter.y > m_PicCtrlHeight - fitSizeImgHeight)
{
LeftUpAfter.y = m_PicCtrlHeight - fitSizeImgHeight;
}
// 实际偏移量
shift.x = LeftUpAfter.x - LeftUpBefore.x;
shift.y = LeftUpAfter.y - LeftUpBefore.y;
cvSetImageROI(fillblackImg, cvRect(static_cast<int>(LeftUpAfter.x), static_cast<int>(LeftUpAfter.y), fitSizeImgWidth, fitSizeImgHeight));
cvAdd(fillblackImg, fitSizeImg, fillblackImg);
cvResetImageROI( fillblackImg );
// 设置 ShowRegionOnScreen : 图像显示部分在dialog中的坐标
m_ShowRegionOnScreen.left = LeftUpAfter.x;
m_ShowRegionOnScreen.right = LeftUpAfter.x + fitSizeImgWidth;
m_ShowRegionOnScreen.top = LeftUpAfter.y;
m_ShowRegionOnScreen.bottom = LeftUpAfter.y + fitSizeImgHeight;
// 在图像中写字、添加信息示例
if (m_LatestQBData.image.bValid == true)
{
cv::Mat fillblackImgMat(fillblackImg, false);
cv::Scalar color(0, 255, 0);
if (fillblackImgMat.type() == CV_8UC1)
{
color = cv::Scalar(255);
}
// 图像显示比例
CString scale = 0;
scale.Format("%.1f", double(fitSizeImgWidth) / imgWidth * 100);
scale = scale + "%";
cv::putText(fillblackImgMat, scale.GetBuffer(0), cv::Point(10, fillblackImgMat.rows - 20), 2, 0.5, color);
}
// 释放 fitSizeImg
cvReleaseImage(&fitSizeImg);
fitSizeImg = NULL;
// 绘图
CvvImage img;
img.CopyOf(fillblackImg);
img.Show(hdc, 0, 0, fillblackImg->width, fillblackImg->height);
// 释放fillblackImg
cvReleaseImage(&fillblackImg);
fillblackImg = NULL;
// 释放
ReleaseDC(pDC);
return TRUE;
}
catch(cv::Exception &e)
{
e.msg;
return FALSE;
}
catch(...)
{
return FALSE;
}
}
// 1.5 功能:设置目标点像素坐标,如果设置合理,在在显示窗口中标绘目标
BOOL CImgShowDlg::SetTargetPixelCoordinate(const CPoint &point)
{
try
{
// 设置目标点
m_LButtonDblClkPixelCoordinate = point; // 赋值给私有成员变量
if ((point.x >= m_ShowRegion.left) && (point.x <= m_ShowRegion.right) &&
(point.y >= m_ShowRegion.top) && (point.y <= m_ShowRegion.bottom) )
{
// 标绘目标:当目标点未显示到屏幕时,不标绘
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
}
else
{
// 先全景显示 再标绘
OnZoomFitImg();
// 标绘目标:当目标点未显示到屏幕时,不标绘
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
}
return TRUE;
}
catch(cv::Exception &e)
{
e.msg;
return FALSE;
}
catch(...)
{
return FALSE;
}
}
// 功能:标绘目标,其中输入为经纬度坐标
void CImgShowDlg::SetTgtLocLeadLonLat(double lon, double lat)
{
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
return;
}
if (m_SrcFrame != NULL && m_SrcFrame->width > 0 && m_SrcFrame->height > 0)
{
if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0
&& m_boundbingBox.WestLon >= -180
&& m_boundbingBox.WestLon <= 180
&& m_boundbingBox.EastLon >= -180
&& m_boundbingBox.EastLon <= 180
&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0
&& m_boundbingBox.SouthLat >= -90
&& m_boundbingBox.SouthLat <= 90
&& m_boundbingBox.NorthLat >= -90
&& m_boundbingBox.NorthLat <= 90)
{
if (lon >= m_boundbingBox.WestLon
&& lon <= m_boundbingBox.EastLon
&& lat >= m_boundbingBox.SouthLat
&& lat <= m_boundbingBox.NorthLat)
{
double LonResolution = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / m_SrcFrame->width;
double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;
CPoint pixelCord;
pixelCord.x = static_cast<LONG>((lon - m_boundbingBox.WestLon) / LonResolution);
pixelCord.y = static_cast<LONG>((m_boundbingBox.NorthLat - lat) / LatResolution);
SetTargetPixelCoordinate(pixelCord);
}
}
else
{
::MessageBoxA(NULL, _T("目标可能不在当前图像中!"),_T("操作提示"), MB_OK);
}
}
}
// 绘制四个角点连成的区域
BOOL CImgShowDlg::SetQuadrangleCorners(const POINT* pts)
{
try
{
if (pts != NULL)
{
m_corners[0] = pts[0];
m_corners[1] = pts[1];
m_corners[2] = pts[2];
m_corners[3] = pts[3];
POINT CornersOnScreen[4];
for (int i = 0; i < 4; i++)
{
CornersOnScreen[i] = GetScreenCoordinateBasedOnPixelCoordinate(m_corners[i]);
}
if (CornersOnScreen[0].x >= 0 && CornersOnScreen[0].y >= 0 &&
CornersOnScreen[1].x >= 0 && CornersOnScreen[1].y >= 0 &&
CornersOnScreen[2].x >= 0 && CornersOnScreen[2].y >= 0 &&
CornersOnScreen[3].x >= 0 && CornersOnScreen[3].y >= 0)
{
DrawQuadrangleOnScreen(CornersOnScreen);
}
return TRUE;
}
}
catch(cv::Exception &e)
{
e.msg;
return FALSE;
}
catch(...)
{
return FALSE;
}
return FALSE;
}
// 1.6 功能:绘制指北针
// void CImgShowDlg::DrawNorthDirection(const POINT &center, double angle)
// {
// try
// {
// int r = 20; // 中心点到底角的长度
// int R = 30; // 中心点到顶点的长度
//
// double LocalAngle = 50.0; // 控制指北针尖锐程度
// LocalAngle = LocalAngle/180.0 * 3.1415926535;
//
// CDC* pDC = NULL;
// pDC = this->GetDC();
//
// // 判断若pDC为空直接返回后面程序也无需再判定pDC
// if (pDC == NULL)
// {
// return;
// }
//
// // 创建并选择画笔
// CPen aPen;
// aPen.CreatePen(PS_SOLID, 2, RGB(0,255,0));
//
// CPen * pOldPen = NULL;
// pOldPen = pDC->SelectObject(&aPen);
//
// // 设置背景透明 用于写字
// pDC->SetBkMode(TRANSPARENT);
// pDC->SetTextColor(RGB(0,255,0));
//
// // 绘制图形需要的五个点
// POINT point[5];
//
// // 零度时各点相对于中心点的位置
// point[0].x = - static_cast<LONG>(r * cos(LocalAngle));
// point[0].y = static_cast<LONG>(r * sin(LocalAngle));
//
// point[1].x = 0L;
// point[1].y = - static_cast<LONG>(R);
//
// point[2].x = static_cast<LONG>(r * cos(LocalAngle));
// point[2].y = static_cast<LONG>(r * sin(LocalAngle));
//
// point[3].x = 0L;
// point[3].y = 0L;
//
// point[4].x = - 4L;
// point[4].y = - static_cast<LONG>(R + 16);
//
// // 各点旋转一定角度并平移至以center为中心的坐标
// for(int i = 0; i < 5; i++)
// {
// point[i] = RotateShiftPoint(point[i],angle,center);
// }
//
// // 绘图
// pDC->MoveTo(point[0]);
// pDC->LineTo(point[1]);
// pDC->LineTo(point[2]);
// pDC->LineTo(point[3]);
// pDC->LineTo(point[0]);
//
// // 画圆圈
// CBrush* pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
// CBrush* pOldBrush = pDC->SelectObject(pBrush);
// R = R + 2;
// pDC->Ellipse(point[3].x - R, point[3].y - R, point[3].x + R, point[3].y + R);
// pDC->SelectObject(pOldBrush);
//
// // 写字N
// // 转换为【0360】
// angle = (angle/360.0 - static_cast<int>(angle/360.0)) * 360.0;
// if (angle < 0)
// {
// angle += 360;
// }
//
// // 判断并修正,经验值
// if (angle <= 45)
// {
// point[4].y -= 3;
// }
//
// if ((angle > 45) && (angle <= 135))
// {
// point[4].x -= 8;
// point[4].y -= 3;
// }
//
// if ((angle > 135) && (angle <= 225))
// {
// point[4].x -= 8;
// point[4].y -= 10;
// }
//
// if ((angle > 225) && (angle <= 315))
// {
// point[4].y -= 10;
// }
//
// if (angle > 315)
// {
// point[4].y -= 6;
// }
//
// // 写N
// pDC->TextOutA(static_cast<int>(point[4].x), static_cast<int>(point[4].y), "N");
//
// // 选回旧画笔
// pDC->SelectObject(pOldPen);
//
// // 释放pDC
// ReleaseDC(pDC);
// pDC = NULL;
// }
// catch(cv::Exception &e)
// {
// e.msg;
// return;
// }
// catch(...)
// {
// return;
// }
// }
//
// //1.7 功能:设置指北针中心
// void CImgShowDlg::SetNorthDirectionCenter(const POINT &center)
// {
// CRect rect;
// GetClientRect(&rect);
//
// if ((center.x > 0) && (center.x < rect.Width()) &&
// (center.y > 0) && (center.y < rect.Height()))
// {
// m_NorthDirectionCenter = center;
// }
// }
// 1.8 功能基于私有成员变量LatestQBData 显示图像和指北针
// 说明当dst有效时优先显示dst否则显示src
void CImgShowDlg::ShowLatestQBData()
{
try
{
// geoImg
if ((m_LatestQBData.image.bValid == true) && // 图像数据有效
(m_LatestQBData.image.geoImg.buff != nullptr) && // 图像有数据
(m_LatestQBData.image.geoImg.ImgWidth > 0) && (m_LatestQBData.image.geoImg.ImgHeight > 0) && // 图像尺寸有效
(m_LatestQBData.image.geoImg.bitcount > 0)) // 数据位数有效
{
// 创建临时变量:图像头
BITMAPINFO imgheader;
imgheader.bmiHeader.biWidth = static_cast<int>(m_LatestQBData.image.geoImg.ImgWidth);
imgheader.bmiHeader.biHeight = static_cast<int>(m_LatestQBData.image.geoImg.ImgHeight);
imgheader.bmiHeader.biBitCount = static_cast<WORD>(m_LatestQBData.image.geoImg.bitcount);
// 显示图像
ShowOneImage(&imgheader, m_LatestQBData.image.geoImg.buff, FALSE, NULL, FALSE, m_ImgRatioOnScreen, m_ImgShowShift);
if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
{
m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
}
}
// dstImg
else if ((m_LatestQBData.image.bValid == true) && // 图像数据有效
(m_LatestQBData.image.dstImg.buff != nullptr) && // 图像有数据
(m_LatestQBData.image.dstImg.ImgWidth > 0) && (m_LatestQBData.image.dstImg.ImgHeight > 0) && // 图像尺寸有效
(m_LatestQBData.image.dstImg.bitcount > 0)) // 数据位数有效
{
// 创建临时变量:图像头
BITMAPINFO imgheader;
imgheader.bmiHeader.biWidth = static_cast<int>(m_LatestQBData.image.dstImg.ImgWidth);
imgheader.bmiHeader.biHeight = static_cast<int>(m_LatestQBData.image.dstImg.ImgHeight);
imgheader.bmiHeader.biBitCount = static_cast<WORD>(m_LatestQBData.image.dstImg.bitcount);
// 显示图像
ShowOneImage(&imgheader, m_LatestQBData.image.dstImg.buff, FALSE, NULL, FALSE, m_ImgRatioOnScreen, m_ImgShowShift);
if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
{
m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
}
}
// srcImg
else if ((m_LatestQBData.image.bValid == true) && // 图像数据有效
(m_LatestQBData.image.srcImg.buff != nullptr) && // 图像有数据
(m_LatestQBData.image.srcImg.ImgWidth > 0) && (m_LatestQBData.image.srcImg.ImgHeight > 0) && // 图像尺寸有效
(m_LatestQBData.image.srcImg.bitcount > 0)) // 数据位数有效
{
// 创建临时变量:图像头
BITMAPINFO imgheader;
imgheader.bmiHeader.biWidth = static_cast<LONG>(m_LatestQBData.image.srcImg.ImgWidth);
imgheader.bmiHeader.biHeight = static_cast<LONG>(m_LatestQBData.image.srcImg.ImgHeight);
imgheader.bmiHeader.biBitCount = static_cast<WORD>(m_LatestQBData.image.srcImg.bitcount);
// 显示图像
ShowOneImage(&imgheader, m_LatestQBData.image.srcImg.buff, FALSE, NULL, FALSE, m_ImgRatioOnScreen, m_ImgShowShift);
if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
{
m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
}
}
else // 图像数据无效
{
// 如果当前帧图像数据无效,则释放上一帧保存的图像
cvReleaseImage(&m_SrcFrame);
m_SrcFrame = NULL;
// 重绘窗口
CRect clientRect;
GetClientRect(&clientRect);
InvalidateRect(&clientRect);
UpdateWindow();
// 显示指北针
if (m_LatestQBData.framePart.bValid == TRUE) // 复接数据有效
{
// 设置在OnPaint中不绘制指北针
m_bPlotDirectionOnPaint = FALSE;
// 清除上次绘制的指北针
CRect rect;
rect.left = m_NorthDirectionCenter.x - 100;
rect.right = m_NorthDirectionCenter.x + 100;
rect.top = m_NorthDirectionCenter.y - 100;
rect.bottom = m_NorthDirectionCenter.y + 100;
InvalidateRect(&rect);
UpdateWindow();
// 恢复设置 OnPaint中重绘
m_bPlotDirectionOnPaint = TRUE;
}
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 1.9 功能:获取双击目标点坐标 m_LButtonDblClkPixelCoordinate
CPoint CImgShowDlg::GetTargetCoordinate()
{
return m_LButtonDblClkPixelCoordinate;
}
// 1.10 功能:在对话框左上角显示信息
void CImgShowDlg::ShowMessageOnDialog(CString msg)
{
try
{
// 获取窗口句柄
CWnd *pWnd = GetDlgItem(IDC_IMG_SHOW_PIC_CTRL);
CRect Rect;
pWnd->GetClientRect(&Rect);
// 获得控件的 DC
CDC *pDC=pWnd->GetDC();
// 设置背景透明
pDC->SetBkMode(TRANSPARENT);
// 设置字体颜色
pDC->SetTextColor(RGB(255,0,0));
// 输出信息
pDC->TextOutA(Rect.Width() - 130, Rect.Height() - 50, msg);
ReleaseDC(pDC);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 3.1 功能:基于当前图像显示状态 和 像素坐标(图像某点的像素坐标),求该像素坐标对应的客户区坐标
CPoint CImgShowDlg::GetScreenCoordinateBasedOnPixelCoordinate(const POINT &PixelCoordinate)
{
// 返回值
CPoint screenCoordinate = CPoint(-100, -100);
try
{
// 如果该像素坐标显示在当前窗口中
if ((PixelCoordinate.x >= m_ShowRegion.left) && (PixelCoordinate.x <= m_ShowRegion.right) &&
(PixelCoordinate.y >= m_ShowRegion.top) && (PixelCoordinate.y <= m_ShowRegion.bottom) )
{
double ratio = 1.0;
// 计算屏幕坐标
if(m_ShowRegionOnScreen.Width() > 0)
{
ratio = m_ShowRegion.Width() * 1.0 / m_ShowRegionOnScreen.Width();
if (ratio > 0.0)
{
screenCoordinate.x = static_cast<LONG>((PixelCoordinate.x - m_ShowRegion.left) / ratio) + m_ShowRegionOnScreen.left;
screenCoordinate.y = static_cast<LONG>((PixelCoordinate.y - m_ShowRegion.top) / ratio) + m_ShowRegionOnScreen.top;
}
}
}
return screenCoordinate;
}
catch(cv::Exception &e)
{
e.msg;
return screenCoordinate;
}
catch(...)
{
return screenCoordinate;
}
}
// 3.2 功能:给定屏幕坐标,在屏幕中绘制标框, (可能)同时清除上次绘制的标框
void CImgShowDlg::DrawSquareOnScreen(const POINT &screenCoordinate, BOOL bErase)
{
try
{
// 如果该点在图像显示区域中,则清除上次绘制的标框,同时标绘该点
int X = static_cast<int>(screenCoordinate.x); // X坐标
int Y = static_cast<int>(screenCoordinate.y); // Y坐标
if (X > m_ShowRegionOnScreen.left && X < m_ShowRegionOnScreen.right &&
Y > m_ShowRegionOnScreen.top && Y < m_ShowRegionOnScreen.bottom ) // 鼠标在图像上
{
// 绘制标框
if (bErase == TRUE)
{
// 去掉上次标绘的框
InvalidateRect(&m_LatestPlotRect, FALSE);
UpdateWindow();
}
CDC* pDC = this->GetDC();
CPen newPen; // 创建新画笔
newPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0));
CPen* pOldPen = NULL;
if (pDC != NULL)
{
pDC->SelectObject(&newPen);
// 绘图
pDC->MoveTo(X - 50, Y);
pDC->LineTo(X - 20, Y);
pDC->MoveTo(X + 20, Y);
pDC->LineTo(X + 50, Y);
pDC->MoveTo(X, Y - 50);
pDC->LineTo(X, Y - 20);
pDC->MoveTo(X, Y + 20);
pDC->LineTo(X, Y + 50);
pDC->MoveTo(X + 30, Y - 15);
pDC->LineTo(X + 30, Y - 30);
pDC->LineTo(X + 15, Y - 30);
pDC->MoveTo(X - 30, Y - 15);
pDC->LineTo(X - 30, Y - 30);
pDC->LineTo(X - 15, Y - 30);
pDC->MoveTo(X - 30, Y + 15);
pDC->LineTo(X - 30, Y + 30);
pDC->LineTo(X - 15, Y + 30);
pDC->MoveTo(X + 30, Y + 15);
pDC->LineTo(X + 30, Y + 30);
pDC->LineTo(X + 15, Y + 30);
// 中心点
pDC->MoveTo(X - 1, Y);
pDC->LineTo(X + 1, Y);
pDC->MoveTo(X , Y - 1);
pDC->LineTo(X , Y + 1);
// 回收旧画笔
pDC->SelectObject(pOldPen);
// 释放设备上下文指针
ReleaseDC(pDC);
pDC = NULL;
// 更新latestRect
m_LatestPlotRect.left = X - 51;
m_LatestPlotRect.right = X + 50;
m_LatestPlotRect.top = Y - 51;
m_LatestPlotRect.bottom = Y + 50;
}
// 设置为目标标绘状态
m_bPlotRect = TRUE;
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 3.2 功能给定屏幕4个坐标在屏幕中绘制四边形, (可能)同时清除上次绘制
// 输入:
// 1: screenCoordinate: 屏幕坐标
// 返回值:无
void CImgShowDlg::DrawQuadrangleOnScreen(const POINT screenCoordinate[4], BOOL bErase)
{
try
{
// 如果该点在图像显示区域中,则清除上次绘制的标框,同时标绘该点
// 绘制标框
if (bErase == TRUE)
{
// 去掉上次标绘的框
InvalidateRect(&m_LatestPlotRect, FALSE);
UpdateWindow();
}
CDC* pDC = this->GetDC();
CPen newPen; // 创建新画笔
newPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0));
CPen* pOldPen = NULL;
if (pDC != NULL)
{
pDC->SelectObject(&newPen);
// 绘图
pDC->MoveTo(screenCoordinate[0].x, screenCoordinate[0].y);
pDC->LineTo(screenCoordinate[1].x, screenCoordinate[1].y);
pDC->LineTo(screenCoordinate[2].x, screenCoordinate[2].y);
pDC->LineTo(screenCoordinate[3].x, screenCoordinate[3].y);
pDC->LineTo(screenCoordinate[0].x, screenCoordinate[0].y);
// 回收旧画笔
pDC->SelectObject(pOldPen);
// 释放设备上下文指针
ReleaseDC(pDC);
pDC = NULL;
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::DoZoomInImg()
{
try
{
/************************************************************************/
/* 设计思路:
分两种情况:
情况1当前图像的全部内容已经全部显示出来
情况2当前只显示出部分图像
针对情况1也存在两种情况
1.1 全景显示: 此时 StrecthRatio = 1.0f
1.2 图像已经经过缩小显示此时StrecthRatio <= 0.901(考虑到存储精度)这时放大10%显示即可即StrecthRatio /= 0.9f;
针对情况2只显示出部分图像此时 StrecthRatio = 1.0f
/************************************************************************/
if ((m_ShowRegion.Width() == m_SrcFrame->width - 1) && (m_ShowRegion.Height() == m_SrcFrame->height - 1)) // 情况1
{
// 拉伸比例计算
if (m_ImgRatioOnScreen <= 0.901F) // (1.2) 目前图像是缩小显示
{
m_ImgRatioOnScreen /= 0.9F;
}
else // (1.1) 目前图像是充满显示,正好
{
m_ImgRatioOnScreen = 1.0F; // 继续放大时要求继续填满显示才符合逻辑故设为ImgRatioOnScreen = 1.0F
if (max(m_ShowRegion.Width(), m_ShowRegion.Height()) >= 100)
{
m_ShowRegion = GetNewRegionWhenZoom(true);
}
}
}
else // 图像尚未完整显示 情况2
{
m_ImgRatioOnScreen = 1.0F; // 此时,无需拉伸比例控制
if (max(m_ShowRegion.Width(), m_ShowRegion.Height()) >= 100)
{
m_ShowRegion = GetNewRegionWhenZoom(true);
}
}
// 显示图像
ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);
int a = 5;
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
CRect CImgShowDlg::GetNewRegionWhenZoom(bool in)
{
CRect newShowRegion = m_ShowRegion;
try
{
double ratio = 0.1;
if (in == true)
{
ratio = -ratio;
}
// 在当前显示区域的基础上,以中心点为基准点放大
int ShowRegionWidth = m_ShowRegion.Width() + 1;
int ShowRegionHeight = m_ShowRegion.Height() + 1;
newShowRegion.left = m_ShowRegion.left - static_cast<LONG>(ratio / 2 * ShowRegionWidth);
newShowRegion.right = m_ShowRegion.right + static_cast<LONG>(ratio / 2 * ShowRegionWidth);
newShowRegion.top = m_ShowRegion.top - static_cast<LONG>(ratio / 2 * ShowRegionHeight);
newShowRegion.bottom = m_ShowRegion.bottom + static_cast<LONG>(ratio / 2 * ShowRegionHeight);
// 在此修正,确保返回值有效
if (newShowRegion.left < 0)
{
newShowRegion.left = 0;
}
int _Width = m_SrcFrame->width;
int _Height = m_SrcFrame->height;
if (newShowRegion.right > _Width - 1)
{
newShowRegion.right = _Width - 1;
}
if (newShowRegion.top < 0)
{
newShowRegion.top = 0;
}
if (newShowRegion.bottom > _Height - 1)
{
newShowRegion.bottom = _Height - 1;
}
// 若无效,返回原始值
if (newShowRegion.right - newShowRegion.left <= 0 ||
newShowRegion.bottom - newShowRegion.top <= 0)
{
return m_ShowRegion;
}
// 调整 newShowRegion 目的:填充图像控件
double newShowRegion_WH_Ration = 1.0; // 当前 newShowRegion 的“宽高” 比例
double PicCtrl_WH_Ration = 1.0; // 当前图像控件的“宽高”比例
double newShowRegion_HW_Ration = 1.0; // 当前 newShowRegion 的“高宽”比例
double PicCtrl_HW_Ration = 1.0; // 当前图像控件的“高宽”比例
// 分母不为0判断
if ((newShowRegion.Height() > 0) && (m_PicCtrlHeight > 0))
{
newShowRegion_WH_Ration = static_cast<double>(newShowRegion.Width()) / static_cast<double>(newShowRegion.Height());
PicCtrl_WH_Ration = static_cast<double>(m_PicCtrlWidth) / static_cast<double>(m_PicCtrlHeight);
}
else
{
return m_ShowRegion;
}
// 分母不为0判断
if ((newShowRegion_WH_Ration > 0.0) && (PicCtrl_WH_Ration > 0.0))
{
newShowRegion_HW_Ration = 1.0 / newShowRegion_WH_Ration;
PicCtrl_HW_Ration = 1.0 / PicCtrl_WH_Ration;
}
else
{
return m_ShowRegion;
}
if (newShowRegion_WH_Ration > PicCtrl_WH_Ration) // 宽度已经填满时
{
// 图像上下填充
int newShowRegion_ideal_Height = 0; // 在现有图像显示宽度的基础上,图像显示区域的理想高度
newShowRegion_ideal_Height = static_cast<int>(newShowRegion.Width() * PicCtrl_HW_Ration);
// 上下补齐
newShowRegion.top -= static_cast<LONG>((newShowRegion_ideal_Height - newShowRegion.Height() + 1)/ 2); // + 1 是考虑到 0.5 误差影响
newShowRegion.bottom += static_cast<LONG>((newShowRegion_ideal_Height - newShowRegion.Height() + 1)/ 2); // + 1 是考虑到 0.5 误差影响
// 补齐后有可能越界 需进行修正
if (newShowRegion.top < 0) // 可能上边界越出图像边界
{
newShowRegion.bottom -= newShowRegion.top;
newShowRegion.top = 0L;
if (newShowRegion.bottom > static_cast<LONG>(_Height - 1))
{
newShowRegion.bottom = static_cast<LONG>(_Height - 1);
}
}
if (newShowRegion.bottom > static_cast<LONG>(_Height - 1)) // 可能下边界越出图像边界
{
newShowRegion.top -= static_cast<LONG>((newShowRegion.bottom - _Height + 1));
newShowRegion.bottom = static_cast<LONG>(_Height - 1);
if (newShowRegion.top < 0L)
{
newShowRegion.top = 0L;
}
}
}
else // 高度已经填满
{
// 图像左右填充
int newShowRegion_ideal_Width = 0; // 在现有图像显示高度的基础上,图像显示区域的理想宽度
newShowRegion_ideal_Width = static_cast<int>(newShowRegion.Height() * PicCtrl_WH_Ration);
// 左右补齐
newShowRegion.left -= static_cast<LONG>((newShowRegion_ideal_Width - newShowRegion.Width() + 1)/ 2); // + 1 是考虑到 0.5 误差影响
newShowRegion.right += static_cast<LONG>((newShowRegion_ideal_Width - newShowRegion.Width() + 1)/ 2); // + 1 是考虑到 0.5 误差影响
// 补齐后有可能越界 需进行修正
if (newShowRegion.left < 0L) // 可能左边界越出图像边界
{
newShowRegion.right -= newShowRegion.left;
newShowRegion.left = 0L;
if (newShowRegion.right > static_cast<LONG>(_Width - 1))
{
newShowRegion.right = static_cast<LONG>(_Width - 1);
}
}
if (newShowRegion.right > static_cast<LONG>(_Width - 1)) // 可能右边界越出图像边界
{
newShowRegion.left -= static_cast<LONG>((newShowRegion.right - _Width + 1));
newShowRegion.right = static_cast<LONG>(_Width - 1);
if (newShowRegion.left < 0L)
{
newShowRegion.left = 0L;
}
}
}
// 在此修正,确保返回值有效
if (newShowRegion.left < 0)
{
newShowRegion.left = 0;
}
if (newShowRegion.right > _Width - 1)
{
newShowRegion.right = _Width - 1;
}
if (newShowRegion.top < 0)
{
newShowRegion.top = 0;
}
if (newShowRegion.bottom > _Height - 1)
{
newShowRegion.bottom = _Height - 1;
}
return newShowRegion;
}
catch(cv::Exception &e)
{
e.msg;
return newShowRegion;
}
catch(...)
{
return newShowRegion;
}
}
// 3.6 功能: 执行图像缩小操作
void CImgShowDlg::DoZoomOutImg()
{
try
{
// 计算图像显示区域更新ShowRegion
/************************************************************************/
/* 设计思路:
分两种情况:
情况1当前图像的全部内容已经全部显示出来继续拉伸比例缩小显示即可
情况2当前只显示出部分图像计算新的显示区域
/************************************************************************/
// 是否已经显示全部图像内容
if ((m_ShowRegion.Width() == m_SrcFrame->width - 1) && (m_ShowRegion.Height() == m_SrcFrame->height - 1))
{
if (max(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) > 10)
{
m_ImgRatioOnScreen *= 0.9F;
}
}
else // 图像尚未完整显示
{
// 自适应计算 ShowRegion
m_ShowRegion = GetNewRegionWhenZoom(false);
m_ImgRatioOnScreen = 1.0F; // 此时,无需拉伸比例控制
}
// 显示图像
ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 3.7 功能: 当漫游图像时,自适应计算新的图像显示区
CRect CImgShowDlg::GetNewRegionWhenRoamImg(int deltaX, int deltaY)
{
// 返回值,初始化为当前显示区域
CRect newShowRegion = m_ShowRegion; // 新的图像显示区域
newShowRegion.left = m_ShowRegion.left - deltaX;
newShowRegion.right = m_ShowRegion.right - deltaX;
newShowRegion.top = m_ShowRegion.top - deltaY;
newShowRegion.bottom = m_ShowRegion.bottom - deltaY;
int m_Width = m_SrcFrame->width;
int m_Height = m_SrcFrame->height;
if (newShowRegion.left < 0L)
{
newShowRegion.right -= newShowRegion.left;
newShowRegion.left = 0L;
if (newShowRegion.right > static_cast<LONG>(m_Width - 1))
{
newShowRegion.right = static_cast<LONG>(m_Width - 1);
}
}
if (newShowRegion.right > static_cast<LONG>(m_Width - 1))
{
newShowRegion.left -= static_cast<LONG>((newShowRegion.right - m_Width + 1));
newShowRegion.right = static_cast<LONG>(m_Width - 1);
if (newShowRegion.left < 0L)
{
newShowRegion.left = 0L;
}
}
if (newShowRegion.top < 0)
{
newShowRegion.bottom -= newShowRegion.top;
newShowRegion.top = 0L;
if (newShowRegion.bottom > static_cast<LONG>(m_Height - 1))
{
newShowRegion.bottom = static_cast<LONG>(m_Height - 1);
}
}
if (newShowRegion.bottom > static_cast<LONG>(m_Height - 1))
{
newShowRegion.top -= static_cast<LONG>((newShowRegion.bottom - m_Height + 1));
newShowRegion.bottom = static_cast<LONG>(m_Height - 1);
if (newShowRegion.top < 0L)
{
newShowRegion.top = 0L;
}
}
// 在此修正,确保返回值有效
if (newShowRegion.left < 0)
{
newShowRegion.left = 0;
}
if (newShowRegion.right > m_Width - 1)
{
newShowRegion.right = m_Width - 1;
}
if (newShowRegion.top < 0)
{
newShowRegion.top = 0;
}
if (newShowRegion.bottom > m_Height - 1)
{
newShowRegion.bottom = m_Height - 1;
}
return newShowRegion;
}
// 3.8 功能: 执行图像全景(全屏)操作
void CImgShowDlg::DoZoomFitImg()
{
try
{
// 保证有图像
if (m_SrcFrame != NULL)
{
// 设置为整个图像显示
m_ShowRegion.left = 0L;
m_ShowRegion.right = static_cast<LONG>(m_SrcFrame->width - 1);
m_ShowRegion.top = 0L;
m_ShowRegion.bottom = static_cast<LONG>(m_SrcFrame->height - 1);
// 拉伸比例归1
m_ImgRatioOnScreen = 1.0F; // 复位
// 平移量归零
m_ImgShowShift.x = 0L;
m_ImgShowShift.y = 0L;
// 全景显示图像
ShowWholeImage(m_SrcFrame, m_ImgRatioOnScreen, m_ImgShowShift);
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// CImgShowDlg 消息处理程序
BOOL CImgShowDlg::OnEraseBkgnd(CDC* pDC)
{
// 背景色为黑色
CRect Rect;
GetClientRect(&Rect);
pDC->FillSolidRect(Rect, RGB(0, 0, 0)); //设置窗口背景颜色为黑色
return TRUE;
}
void CImgShowDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
try
{
if (m_SrcFrame != NULL)
{
// 重绘图像
ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);
if (min(m_ShowRegionOnScreen.Width(), m_ShowRegionOnScreen.Height()) <= 10)
{
m_ImgRatioOnScreen = m_ImgRatioOnScreen / 0.9F;
}
if (m_bPlotRectOnPaint == TRUE)
{
// 标绘目标点 标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);
}
// 视场标绘
// SetQuadrangleCorners(m_corners);
}
else
{
if (m_sThemeText != "")
{
// 写字:图像窗口
// 获取窗口句柄
CWnd *pWnd = NULL;
pWnd = GetDlgItem(IDC_IMG_SHOW_PIC_CTRL);
if (pWnd == NULL)
{
return;
}
// 获得控件的 DC
CDC *pDC = NULL;
pDC = pWnd->GetDC();
if (pDC == NULL)
{
return;
}
CFont font;
font.CreatePointFont(180,"Times New Roman");
CFont *pOldFont = pDC->SelectObject(&font);
// 设置背景透明
pDC->SetBkMode(TRANSPARENT);
// 设置字体颜色
pDC->SetTextColor(RGB(0,255,255));
// 确定输出位置
CRect Rect;
GetClientRect(&Rect);
int x = Rect.left + 5;
int y = Rect.bottom - 28;
// 输出信息
pDC->TextOutA(x, y, m_sThemeText);
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);
}
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 5.10 右键响应函数
// 功能:弹出右键菜单,进行功能选择
void CImgShowDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
try
{
if (m_bCloseRughtBtnMenu == false)
{
// 加载菜单项
CMenu menu;
menu.LoadMenu(IDR_MENU_IMG_PROCESS);
// 保留右键坐标 由于定位导引 或 右键图像放大
m_RButtonPt = point;
// 输入坐标为客户区坐标,也就是相对本对话框左上角为0,0的坐标转换到屏幕坐标
ClientToScreen(&point);
// 九宫格快速浏览图像
if (m_pFastLookUpDlg != NULL && m_pFastLookUpDlg->IsWindowVisible() == TRUE)
{
menu.GetSubMenu(0)->CheckMenuItem(ID_FAST_LOOKUP_IMGS, MF_BYCOMMAND | MF_CHECKED);
}
else
{
menu.GetSubMenu(0)->CheckMenuItem(ID_FAST_LOOKUP_IMGS, MF_BYCOMMAND | MF_UNCHECKED);
}
// menu.GetSubMenu(0)->EnableMenuItem(ID_FAST_LOOKUP_IMGS, MF_GRAYED); // MF_ENABLED
// 标绘 目标 矩形
if (m_bDrawSquareOnImg == TRUE)
{
menu.GetSubMenu(0)->CheckMenuItem(ID_DRAW_SQUARE_ON_IMG, MF_BYCOMMAND | MF_CHECKED);
}
else
{
menu.GetSubMenu(0)->CheckMenuItem(ID_DRAW_SQUARE_ON_IMG, MF_BYCOMMAND | MF_UNCHECKED);
}
// 目标扣取
if (m_bGetTgtImgOn == true)
{
menu.GetSubMenu(0)->CheckMenuItem(ID_GET_TARGET_IMG, MF_BYCOMMAND | MF_CHECKED);
}
else
{
menu.GetSubMenu(0)->CheckMenuItem(ID_GET_TARGET_IMG, MF_BYCOMMAND | MF_UNCHECKED);
}
if (m_bClipImgOn == TRUE)
{
menu.GetSubMenu(0)->CheckMenuItem(ID_CLIP_IMG, MF_BYCOMMAND | MF_CHECKED);
}
else
{
menu.GetSubMenu(0)->CheckMenuItem(ID_CLIP_IMG, MF_BYCOMMAND | MF_UNCHECKED);
}
// 弹出菜单
menu.GetSubMenu(0)->TrackPopupMenu( TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
static_cast<int>(point.x), static_cast<int>(point.y), this); // 只在本窗口内作出相应
}
CDialog::OnRButtonDown(nFlags, point);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:设置图像在屏幕中的显示比例
void CImgShowDlg::SetImgShowRationOnScreen(float ratio)
{
if(ratio >= 1.0F || ratio <= 0.0F)
{
ratio = 1.0F;
}
// 修改全局变量 ImgRatioOnScreen
m_ImgRatioOnScreen = ratio;
}
void CImgShowDlg::OnZoomInImg()
{
try
{
// 如果有外部信号输入,操作与视频模式下相同
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
SetImgShowRationOnScreen(m_ImgRatioOnScreen / 0.9F);
return;
}
// 放大显示图像
DoZoomInImg();
// 更新标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
// 设置无效,不保留上次值
m_RButtonPt.x = -100;
m_RButtonPt.y = -100;
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::OnZoomOutImg()
{
try
{
// 如果有外部信号输入 操作与视频模式下相同
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
SetImgShowRationOnScreen(m_ImgRatioOnScreen * 0.9F);
return;
}
// 缩小显示图像
DoZoomOutImg();
// 更新标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::OnZoomFitImg()
{
try
{
// 如果有外部信号输入 操作与视频模式下相同
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
// 视频显示模式复位
m_ImgRatioOnScreen = 1.0F;
m_ImgShowShift.x = 0L;
m_ImgShowShift.y = 0L;
return;
}
// 直接全景显示图像
DoZoomFitImg();
// 更新标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate));
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::OnConcelTargetPlot()
{
try
{
// 在onPaint中不重绘
m_bPlotRectOnPaint = FALSE;
// 去掉上次标绘的框
InvalidateRect(&m_LatestPlotRect, FALSE);
UpdateWindow(); // 发送消息 立即响应
// 设置为 小于0 的无效值
m_LButtonDblClkPixelCoordinate.x = -1;
m_LButtonDblClkPixelCoordinate.y = -1;
// 结束绘制
m_bPlotRect = FALSE;
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:保存当前帧图像及信息
BOOL CImgShowDlg::SaveCurrentDecodedFrame()
{
try
{
// 计算存储路径
static int imgSaveOrder = 1;
// 图像数据有效
// 说明程序设计中SrcFrame代表当前图像
if (m_SrcFrame != NULL)
{
// 计算图像和复接数据存储路径
SYSTEMTIME CurrentTime;
GetLocalTime(&CurrentTime);
CString ImgSavePath;
ImgSavePath.Format( "%04d%02d%02d_%02d%02d%02d%04d",
CurrentTime.wYear,
CurrentTime.wMonth,
CurrentTime.wDay,
CurrentTime.wHour,
CurrentTime.wMinute,
CurrentTime.wSecond,
CurrentTime.wMilliseconds);
// 添加序号
CString sImgSaveOlder;
sImgSaveOlder.Format("%04d", imgSaveOrder);
ImgSavePath = ImgSavePath + "_" + sImgSaveOlder;
CString FJSavePath;
FJSavePath = ImgSavePath; // 共享同一时间
CString FImgSavePath;
FImgSavePath = ImgSavePath; // 共享同一时间
// 校验保存路径
if (m_sSaveCurrentImgFolder == "" || false == SearchDirectory(m_sSaveCurrentImgFolder))
{
m_sSaveCurrentImgFolder = "";
}
if (m_sSaveCurrentImgFolder == "")
{
ImgSavePath = m_sImgSaveFolder + "\\" + ImgSavePath + ".bmp"; // 完整图像存储路径
}
else
{
ImgSavePath = m_sSaveCurrentImgFolder + "\\" + ImgSavePath + ".bmp"; // 完整图像存储路径
}
// 确保有文件夹,如果中途误删,会再次创建
if (SearchDirectory(m_sRootFolder) == FALSE) // 没找到根文件夹
{
CreateDirectory(m_sRootFolder, NULL);
}
if (SearchDirectory(m_sImgSaveFolder) == FALSE) // 没找到【图像】文件夹
{
CreateDirectory(m_sImgSaveFolder, NULL);
}
// 转化
cv::Mat img(m_SrcFrame, false);
// 保存图像
if (true == cv::imwrite(ImgSavePath.GetBuffer(0), img))
{
// 保存路径回调
if (m_lpSendFilePath != NULL)
{
m_lpSendFilePath(ImgSavePath, 0);
}
}
imgSaveOrder++;
m_sSaveCurrentImgFolder = ""; // 复位
return TRUE;
}
return FALSE;
}
catch(cv::Exception &e)
{
e.msg;
m_sSaveCurrentImgFolder = ""; // 复位
return FALSE;
}
catch(...)
{
m_sSaveCurrentImgFolder = ""; // 复位
return FALSE;
}
}
// 保存当前帧
void CImgShowDlg::OnSaveCurrentFrame()
{
try
{
SaveCurrentDecodedFrame();
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能是否需要记忆前面多帧18帧图像信息
// 输入:
// 1. bMem TRUE记忆 FALSE不记忆
// 输出:无
void CImgShowDlg::MemPreMultiFrame(BOOL bMem)
{
m_bMemPreMultiFrame = bMem;
}
// 左键按下消息响应
void CImgShowDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
try
{
CDialog::OnLButtonDown(nFlags, point);
if (m_SrcFrame == NULL) // 如果没有图像,不响应
{
return;
}
// Alt = 1 Ctrl = 5 Shift = 9
if (nFlags == MK_CONTROL) // 当按住ctrl键时不响应 因为与选择目标时冲突
{
return;
}
// 更新鼠标坐标
m_LeftButtonDown = point;
// 鼠标是否在图像上
if(m_LeftButtonDown.x > m_ShowRegionOnScreen.left && m_LeftButtonDown.x < m_ShowRegionOnScreen.right &&
m_LeftButtonDown.y > m_ShowRegionOnScreen.top && m_LeftButtonDown.y < m_ShowRegionOnScreen.bottom)
{
m_bStaisfyRoamImg = TRUE;
// 计算一点的像素坐标
int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;
m_LButtonDownPixelCoordinate.x = static_cast<int>((point.x - m_ShowRegionOnScreen.left) * ratioW + 0.5 + m_ShowRegion.left);
m_LButtonDownPixelCoordinate.y = static_cast<int>((point.y - m_ShowRegionOnScreen.top) * ratioH + 0.5 + m_ShowRegion.top);
// 图像裁剪优先级高于目标扣取
if (m_bClipImgOn == true)
{
if (m_haveValidFirstPt == FALSE)
{
m_clipImgFirstPt = m_LButtonDownPixelCoordinate;
m_clipImgFirstPtScreen = point;
m_haveValidFirstPt = TRUE;
}
else
{
m_clipImgSecondPt = m_LButtonDownPixelCoordinate;
m_haveValidFirstPt = FALSE;
// 弹出裁剪提示
int Left = min(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
int Right = max(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
int Top = min(m_clipImgFirstPt.y, m_clipImgSecondPt.y);
int Bottom = max(m_clipImgFirstPt.y, m_clipImgSecondPt.y);
if (Right > Left && Bottom > Top)
{
cv::Mat img(m_SrcFrame, false);
cv::Mat clipedImg;
img(cv::Range(Top, Bottom), cv::Range(Left, Right)).copyTo(clipedImg);
int ret = ::MessageBoxA(NULL, _T("确定裁剪图像?"),_T("操作提示"), MB_YESNO | MB_SYSTEMMODAL);
if (ret == IDNO)
{
Invalidate();
}
else
{
m_bClipImgOn = false;
// 创建临时情报结构体
QBStru qbLocal;
qbLocal.image.bValid = true;
qbLocal.framePart.bValid = false;
qbLocal.image.srcImg.ImgWidth = clipedImg.cols;
qbLocal.image.srcImg.ImgHeight = clipedImg.rows;
qbLocal.image.srcImg.bitcount = clipedImg.channels() * 8;
// 步长:每行像素所占字节数
int lineByte = (clipedImg.cols * clipedImg.channels());
// 位图数据缓冲区的大小,即图像大小
int imgBufSize = clipedImg.rows * lineByte;
if (imgBufSize > 0)
{
qbLocal.image.srcImg.buff = new BYTE[imgBufSize];
if (qbLocal.image.srcImg.buff != nullptr)
{
// 复制实际字节数
memcpy(qbLocal.image.srcImg.buff, clipedImg.data, static_cast<size_t>(imgBufSize)); // 图像数据复制
if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0
&& m_boundbingBox.WestLon >= -180
&& m_boundbingBox.WestLon <= 180
&& m_boundbingBox.EastLon >= -180
&& m_boundbingBox.EastLon <= 180
&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0
&& m_boundbingBox.SouthLat >= -90
&& m_boundbingBox.SouthLat <= 90
&& m_boundbingBox.NorthLat >= -90
&& m_boundbingBox.NorthLat <= 90)
{
m_ImgRatioOnScreen = 0.9f;
// 设置经纬度盒子
GeoBoundingBox LLBox;
double lonResolution = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / img.cols;
double latResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / img.rows;
LLBox.WestLon = m_boundbingBox.WestLon + Left * lonResolution;
LLBox.EastLon = m_boundbingBox.WestLon + Right * lonResolution;
LLBox.NorthLat = m_boundbingBox.NorthLat - Top * latResolution;
LLBox.SouthLat = m_boundbingBox.NorthLat - Bottom * latResolution;
qbLocal.image.srcImg.BoundingBox = LLBox;
DisposeQBData(&qbLocal);
SetBoundingBox(LLBox);
SAFE_DELETE_ARRAY(m_midImg.buff);
m_midImg.buff = NULL;
m_iLatest = 0;
}
else
{
if (qbLocal.framePart.bValid == true)
{
int ret = ::MessageBoxA(NULL, _T("提示:图像将丧失定位能力,是否继续?"),_T("操作提示"), MB_OKCANCEL);
if (ret == IDOK)
{
m_ImgRatioOnScreen = 0.9f;
DisposeQBData(&qbLocal);
SAFE_DELETE_ARRAY(m_midImg.buff);
m_midImg.buff = NULL;
m_iLatest = 0;
}
else
{
Invalidate();
}
}
else
{
m_ImgRatioOnScreen = 0.9f;
DisposeQBData(&qbLocal);
SAFE_DELETE_ARRAY(m_midImg.buff);
m_midImg.buff = NULL;
m_iLatest = 0;
}
}
delete [] qbLocal.image.srcImg.buff;
qbLocal.image.srcImg.buff = NULL;
}
}
}
}
}
}
else
{
// 目标扣取
if (m_bGetTgtImgOn == true)
{
if (m_haveValidFirstPt == FALSE)
{
m_clipImgFirstPt = m_LButtonDownPixelCoordinate;
m_clipImgFirstPtScreen = point;
m_haveValidFirstPt = TRUE;
}
else
{
m_clipImgSecondPt = m_LButtonDownPixelCoordinate;
m_haveValidFirstPt = FALSE;
// 弹出裁剪提示
int Left = min(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
int Right = max(m_clipImgFirstPt.x, m_clipImgSecondPt.x);
int Top = min(m_clipImgFirstPt.y, m_clipImgSecondPt.y);
int Bottom = max(m_clipImgFirstPt.y, m_clipImgSecondPt.y);
if (Right > Left && Bottom > Top)
{
cv::Mat img(m_SrcFrame, false);
cv::Mat clipedImg;
img(cv::Range(Top, Bottom), cv::Range(Left, Right)).copyTo(clipedImg);
int ret = ::MessageBoxA(NULL, _T("确定抓取目标图像?"),_T("操作提示"), MB_YESNO | MB_SYSTEMMODAL);
if (ret == IDNO)
{
Invalidate();
}
else
{
m_bGetTgtImgOn = false;
// 计算图像和复接数据存储路径
SYSTEMTIME CurrentTime;
GetLocalTime(&CurrentTime);
CString ImgSavePath;
ImgSavePath.Format( "%04d%02d%02d_%02d%02d%02d%04d.jpg",
CurrentTime.wYear,
CurrentTime.wMonth,
CurrentTime.wDay,
CurrentTime.wHour,
CurrentTime.wMinute,
CurrentTime.wSecond,
CurrentTime.wMilliseconds);
// 确保有文件夹,如果中途误删,会再次创建
CString tgtFolder = GetSoftwareCurrentDirectory() + "\\targets";
if (SearchDirectory(tgtFolder) == FALSE) // 没找到根文件夹
{
CreateDirectory(tgtFolder, NULL);
}
CString savePath = tgtFolder + "\\" + ImgSavePath;
cv::imwrite(savePath.GetBuffer(0) ,clipedImg);
if (m_lpSendFilePath != nullptr)
{
m_lpSendFilePath(savePath, 7);
}
}
}
}
}
}
}
else
{
m_bStaisfyRoamImg = FALSE;
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:向图像中添加 经纬高 位置信息
// 输入:
// 1: qb: 情报结构体
// 2: pt: 像素坐标
// 3. Lon: 经度
// 4. Lat: 纬度
// 5. H: 高度
// 返回值:无
void CImgShowDlg::TagLocationOnImgStru(ImgStru &imgData, cv::Point pt, double Lon, double Lat, double H)
{
try
{
if (imgData.ImgWidth <= 0 || imgData.ImgHeight <= 0
|| (imgData.bitcount != 8 && imgData.bitcount != 24)
|| imgData.buff == NULL)
{
return;
}
if (pt.x < 0 || pt.y < 0)
{
return;
}
if (Lon < -180 || Lon > 180 || Lat < -90 || Lat > 90)
{
return;
}
if (imgData.ImgWidth > 0
&& imgData.ImgHeight > 0
&& (imgData.bitcount == 8 || imgData.bitcount == 24)
&& imgData.buff != NULL)
{
cv::Mat img;
unsigned int imgBufSize = 0;
if (imgData.bitcount == 8 && imgData.ImgHeight * imgData.ImgWidth > 0)
{
img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC1);
imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth);
}
else
if (imgData.bitcount == 24 && imgData.ImgHeight * imgData.ImgWidth * 3 > 0)
{
img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC3);
imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth * 3);
}
memcpy(img.data, imgData.buff, imgBufSize); // 图像数据复制
CString sLon;
CString sLat;
CString sH;
sLon.Format("%.6f", Lon);
sLat.Format("%.6f", Lat);
sH.Format("%.1f", H);
sLon = "Lon:" + sLon;
sLat = "Lat:" + sLat;
sH = "H:" + sH;
cv::Scalar color(0, 255, 255);
cv::circle(img, pt, 2, color, 2);
if (pt.x > (img.cols - 100))
{
cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15), 1, 1, color);
cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15 + 15), 1, 1, color);
cv::putText(img, sH.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 30 + 15), 1, 1, color);
}
else
{
cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4), 1, 1, color);
cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4 + 15), 1, 1, color);
cv::putText(img, sH.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4 + 30), 1, 1, color);
}
memcpy(imgData.buff, img.data, imgBufSize);
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 向图像中写信息
void CImgShowDlg::TagLocationOnQBData(QBStru &qb, cv::Point pt, double Lon, double Lat, double H)
{
try
{
if (qb.image.bValid == true)
{
return;
}
if (pt.x < 0 || pt.y < 0)
{
return;
}
if (Lon < -180 || Lon > 180 || Lat < -90 || Lat > 90)
{
return;
}
// srcImg
TagLocationOnImgStru(qb.image.srcImg, pt, Lon, Lat, H);
// dstImg
TagLocationOnImgStru(qb.image.dstImg, pt, Lon, Lat, H);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:向图像中添加 经纬高 位置信息
// 输入:
// 1: img: 情报结构体
// 2: pt: 像素坐标
// 3. Lon: 经度
// 4. Lat: 纬度
// 5. H: 高度
// 返回值:无
void CImgShowDlg::TagLocationOnMatImg(cv::Mat &img, cv::Point pt, double Lon, double Lat, double H)
{
try
{
if (img.empty() == true || img.cols <= 0 || img.rows <= 0)
{
return;
}
if (pt.x < 0 || pt.y < 0)
{
return;
}
if (Lon < -180 || Lon > 180 || Lat < -90 || Lat > 90)
{
return;
}
CString sLon;
CString sLat;
CString sH;
sLon.Format("%.6f", Lon);
sLat.Format("%.6f", Lat);
sH.Format("%.1f", H);
sLon = "Lon:" + sLon;
sLat = "Lat:" + sLat;
sH = "H:" + sH;
cv::Scalar color(0, 255, 255);
cv::circle(img, pt, 3, color, 2);
if (pt.x > (img.cols - 100))
{
cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15), 1, 1, color);
cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 15 + 15), 1, 1, color);
cv::putText(img, sH.GetBuffer(0), cv::Point(pt.x + 5 - 100, pt.y + 4 + 30 + 15), 1, 1, color);
}
else
{
cv::putText(img, sLon.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4), 1, 1, color);
cv::putText(img, sLat.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4 + 15), 1, 1, color);
cv::putText(img, sH.GetBuffer(0), cv::Point(pt.x + 5, pt.y + 4 + 30), 1, 1, color);
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:向图像中添加 文字 信息
// 输入:
// 1: imgData: 图像结构体
// 2: pt: 像素坐标
// 3. text: 文字信息
// 返回值:无
void CImgShowDlg::TagTextOnImgStru(ImgStru &imgData, cv::Point pt, CString text)
{
try
{
if (imgData.ImgWidth <= 0 || imgData.ImgHeight <= 0
|| (imgData.bitcount != 8 && imgData.bitcount != 24)
|| imgData.buff == NULL)
{
return;
}
if (text == "")
{
return;
}
if (pt.x < 0 || pt.y < 0)
{
return;
}
if (imgData.ImgWidth > 0
&& imgData.ImgHeight > 0
&& (imgData.bitcount == 8 || imgData.bitcount == 24)
&& imgData.buff != NULL)
{
cv::Mat img;
unsigned int imgBufSize = 0;
if (imgData.bitcount == 8)
{
img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC1);
imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth);
}
else
{
img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC3);
imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth * 3);
}
memcpy(img.data, imgData.buff, imgBufSize); // 图像数据复制
cv::Scalar color(0, 255, 255);
cv::putText(img, text.GetBuffer(0), cv::Point(pt.x + 5, pt.y - 5), 1, 1, color);
memcpy(imgData.buff, img.data, imgBufSize);
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:向图像中添加 文字 信息
// 输入:
// 1: qb: 情报结构体
// 2: pt: 像素坐标
// 3. text: 文字信息
// 返回值:无
void CImgShowDlg::TagTextOnQBData(QBStru &qb, cv::Point pt, CString text)
{
try
{
if (qb.image.bValid == 0 || text == "")
{
return;
}
if (pt.x < 0 || pt.y < 0)
{
return;
}
// srcImg
TagTextOnImgStru(qb.image.srcImg, pt, text);
// dstImg
TagTextOnImgStru(qb.image.dstImg, pt, text);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:向图像中添加 文字 信息
// 输入:
// 1: img: 情报结构体
// 2: pt: 像素坐标
// 3. text: 文字信息
// 返回值:无
void CImgShowDlg::TagTextOnMatImg(cv::Mat &img, cv::Point pt, CString text)
{
try
{
if (img.empty() == true || text == "" || img.cols <= 0 || img.rows <= 0)
{
return;
}
if (pt.x < 0 || pt.y < 0)
{
return;
}
cv::Scalar color(0, 255, 255);
cv::putText(img, text.GetBuffer(0), cv::Point(pt.x + 5, pt.y - 5), 1, 1, color);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::TagInfoReviseShotOnMatImg(cv::Mat &img, cv::Point pt1, cv::Point pt2, double *LLA1, double *LLA2)
{
try
{
if (img.empty() == true || img.cols <= 0 || img.rows <= 0)
{
return;
}
if (pt1.x < 0 || pt1.x > img.cols - 1
|| pt1.y < 0 || pt1.y > img.rows - 1)
{
return;
}
if (pt2.x < 0 || pt2.x > img.cols - 1
|| pt2.y < 0 || pt2.y > img.rows - 1)
{
return;
}
if (LLA1[0] < -180 || LLA1[0] > 180 || LLA1[1] < -90 || LLA1[1] > 90)
{
return;
}
if (LLA2[0] < -180 || LLA2[0] > 180 || LLA2[1] < -90 || LLA2[1] > 90)
{
return;
}
// 计算距离和方位
// 计算角度
double distance = 0.0; // 距离
double azAngle = 0.0; // 方位
// 计算两点间的距离和方位(顺时针0 - 360)
CalculateTwoPtsDistanceAzimuth(distance, azAngle, LLA1[0], LLA1[1], LLA2[0], LLA2[1], 3);
// 计算 pt1 和 pt2 在图像中的夹角
const int R = 30;
double theta = 0;
if (pt1.x == pt2.x && pt1.y > pt2.y)
{
theta = 0;
}
else if (pt1.x < pt2.x && pt1.y > pt2.y)
{
theta = atan2(double(pt2.x - pt1.x), double(pt1.y - pt2.y)) * 180 / 3.1415926;
}
else if (pt1.x < pt2.x && pt1.y == pt2.y)
{
theta = 90;
}
else if (pt1.x < pt2.x && pt1.y < pt2.y)
{
theta = atan2(double(pt2.y - pt1.y), double(pt2.x - pt1.x)) * 180 / 3.1415926 + 90;
}
else if (pt1.x == pt2.x && pt1.y < pt2.y)
{
theta = 180;
}
else if (pt1.x > pt2.x && pt1.y < pt2.y)
{
theta = atan2(double(pt1.x - pt2.x), double(pt2.y - pt1.y)) * 180 / 3.1415926 + 180;
}
else if (pt1.x > pt2.x && pt1.y == pt2.y)
{
theta = 270;
}
else
{
theta = atan2(double(pt1.y - pt2.y), double(pt1.x - pt2.x)) * 180 / 3.1415926 + 270;
}
// 计算
cv::Scalar color = cv::Scalar(0,0, 255);
cv::Point pt3;
cv::Point pt4;
pt3.x = pt2.x - static_cast<int>(R * cos((90 - theta - 30) * 3.1415926 / 180));
pt3.y = pt2.y + static_cast<int>(R * sin((90 - theta - 30) * 3.1415926 / 180));
pt4.x = pt2.x - static_cast<int>(R * cos((90 - theta + 30) * 3.1415926 / 180));
pt4.y = pt2.y + static_cast<int>(R * sin((90 - theta + 30) * 3.1415926 / 180));
cv::line(img, pt1, pt2, color, 1, 16);
cv::line(img, pt2, pt3, color, 1, 16);
cv::line(img, pt2, pt4, color, 1, 16);
CString sDistance;
CString sAngle;
if (distance > 1000)
{
sDistance.Format("%.3fkm", distance / 1000);
}
else
{
sDistance.Format("%.1fm", distance);
}
sAngle.Format("%.1fd", azAngle);
color = cv::Scalar(255, 0, 0);
cv::putText(img, sDistance.GetBuffer(0), cv::Point(pt2.x + 5, pt2.y + 4), 1, 1, color);
cv::putText(img, sAngle.GetBuffer(0), cv::Point(pt2.x + 5, pt2.y + 4 + 15), 1, 1, color);
// 写字:“目标”
color = cv::Scalar(0,0, 255);
cv::putText(img, "T", cv::Point(pt1.x, pt1.y), 1, 2, color, 2);
// 火炮校射信息回调输出
if (m_lpSendArtilleryReviseInfo != NULL)
{
m_lpSendArtilleryReviseInfo(float(distance), float(azAngle));
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::TagInfoReviseShotOnImgStru(ImgStru &imgData, cv::Point pt1, cv::Point pt2, double *LLA1, double *LLA2)
{
try
{
if (imgData.ImgWidth <= 0 || imgData.ImgHeight <= 0
|| (imgData.bitcount != 8 && imgData.bitcount != 24)
|| imgData.buff == NULL)
{
return;
}
if (pt1.x < 0 || pt1.x > imgData.ImgWidth - 1
|| pt1.y < 0 || pt1.y > imgData.ImgHeight - 1)
{
return;
}
if (pt2.x < 0 || pt2.x > imgData.ImgWidth - 1
|| pt2.y < 0 || pt2.y > imgData.ImgHeight - 1)
{
return;
}
if (LLA1[0] < -180 || LLA1[0] > 180 || LLA1[1] < -90 || LLA1[1] > 90)
{
return;
}
if (LLA2[0] < -180 || LLA2[0] > 180 || LLA2[1] < -90 || LLA2[1] > 90)
{
return;
}
if (imgData.ImgWidth > 0
&& imgData.ImgHeight > 0
&& (imgData.bitcount == 8 || imgData.bitcount == 24)
&& imgData.buff != NULL)
{
cv::Mat img;
unsigned int imgBufSize = 0;
if (imgData.bitcount == 8)
{
img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC1);
imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth);
}
else
{
img = cv::Mat(imgData.ImgHeight, imgData.ImgWidth, CV_8UC3);
imgBufSize = static_cast<unsigned int>(imgData.ImgHeight * imgData.ImgWidth * 3);
}
memcpy(img.data, imgData.buff, imgBufSize); // 图像数据复制
TagInfoReviseShotOnMatImg(img, pt1, pt2, LLA1, LLA2);
memcpy(imgData.buff, img.data, imgBufSize);
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::TagInfoReviseShotOnQBData(QBStru &qb, cv::Point pt1, cv::Point pt2, double *LLA1, double *LLA2)
{
try
{
if (qb.image.bValid == 0)
{
return;
}
// srcImg
TagInfoReviseShotOnImgStru(qb.image.srcImg, pt1, pt2, LLA1, LLA2);
// dstImg
TagInfoReviseShotOnImgStru(qb.image.dstImg, pt1, pt2, LLA1, LLA2);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 左键双击消息响应
void CImgShowDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
return;
}
try
{
CDialog::OnLButtonDblClk(nFlags, point);
// 要求按住Ctrl键
if ((m_SrcFrame != NULL)/* && (nFlags == MK_CONTROL + 1)*/) // SrcFrame 按住ctrl时nFlags = 9
{
// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
(point.y > m_ShowRegionOnScreen.top) && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
{
// 计算一点的像素坐标
int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;
m_LButtonDblClkPixelCoordinate.x = static_cast<int>((point.x - m_ShowRegionOnScreen.left) * ratioW + 0.5 + m_ShowRegion.left);
m_LButtonDblClkPixelCoordinate.y = static_cast<int>((point.y - m_ShowRegionOnScreen.top) * ratioH + 0.5 + m_ShowRegion.top);
// 地图匹配定位时,在图像中标绘目标
if (m_lpSendTgrLocLeadLonLat != NULL && m_bDrawSquareOnImg == TRUE)
{
cv::Mat DrawTargetImg(m_SrcFrame, false);
cv::Scalar color;
cv::Mat Mask = Mat::zeros(DrawTargetImg.size(), CV_8U);
if (DrawTargetImg.type() == 0)
{
color = cv::Scalar(255);
}
else
{
color = cv::Scalar(0, 0, 255);
}
// 清理上次矩形标绘
cv::Point leftUp = m_TargetCenter + cv::Point(-25, -25);
cv::Point rightUp = m_TargetCenter + cv::Point(+25, -25);
cv::Point rightDown = m_TargetCenter + cv::Point(+25, +25);
cv::Point leftDown = m_TargetCenter + cv::Point(-25, +25);
try
{
cv::line(Mask, leftUp, rightUp, cv::Scalar(255), 1, 16);
cv::line(Mask, leftUp, leftDown, cv::Scalar(255), 1, 16);
cv::line(Mask, leftDown, rightDown, cv::Scalar(255), 1, 16);
cv::line(Mask, rightUp, rightDown, cv::Scalar(255), 1, 16);
cv::inpaint(DrawTargetImg, Mask, DrawTargetImg, 3, CV_INPAINT_TELEA);
}
catch (cv::Exception &e)
{
// 继续执行 即使修补失败,也能输出单点定位结果
e;
}
// 确定矩形四个点
cv::Point center = cv::Point(m_LButtonDblClkPixelCoordinate.x, m_LButtonDblClkPixelCoordinate.y);
leftUp = center + cv::Point(-25, -25);
rightUp = center + cv::Point(+25, -25);
rightDown = center + cv::Point(+25, +25);
leftDown = center + cv::Point(-25, +25);
cv::line(DrawTargetImg, leftUp, rightUp, color, 1, 16);
cv::line(DrawTargetImg, leftUp, leftDown, color, 1, 16);
cv::line(DrawTargetImg, leftDown, rightDown, color, 1, 16);
cv::line(DrawTargetImg, rightUp, rightDown, color, 1, 16);
// 上一次无效时,本次重绘
if (m_TargetCenter.x = -100 && m_TargetCenter.y == -100)
{
OnPaint();
}
// 更新记忆
m_TargetCenter = center;
}
else
{
m_bDrawSquareOnImg = FALSE;
m_TargetCenter = cv::Point(-100, -100);
}
// 绘制标框
// 设计技巧利用m_bPlotRectOnPaint避免在OnPaint中重绘一次
m_bPlotRectOnPaint = FALSE;
DrawSquareOnScreen(point, TRUE);
m_bPlotRectOnPaint = TRUE;
// 函数回调 对外输出目标坐标
if (m_lpSendCoordinate != NULL) // 函数指针有效性判断
{
m_lpSendCoordinate(m_LButtonDblClkPixelCoordinate);
}
// 对外输出像素信息:王家星 20150721 原因:解决多次双击时的像素信息输出问题
//新增功能:计算当前图像 像素坐标 经纬度坐标 RGB值 回调输出
// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
(point.y > m_ShowRegionOnScreen.top) && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
{
// 图像尺寸与显示区域尺寸之间的比例
double ratio = 1.0;
// 分母0值判断
if (m_ShowRegionOnScreen.Width() > 0)
{
ratio = (m_ShowRegion.Width() * 1.0) / m_ShowRegionOnScreen.Width();
}
// 像素坐标
m_imgPixel_XY_Coordinate.x = static_cast<LONG>((point.x - m_ShowRegionOnScreen.left) * ratio) + m_ShowRegion.left;
m_imgPixel_XY_Coordinate.y = static_cast<LONG>((point.y - m_ShowRegionOnScreen.top) * ratio) + m_ShowRegion.top;
// 经纬度坐标
double Lon = 0.0;
double Lat = 0.0;
double H = 0;
if (true == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y))
{
m_imgPixel_LBH_Coordinate.x = Lon + m_deltaLon;
m_imgPixel_LBH_Coordinate.y = Lat + m_deltaLat;
CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";
float fDem = 0;
GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
m_imgPixel_LBH_Coordinate.z = fDem;
}
else
{
if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0
&& m_boundbingBox.WestLon >= -180
&& m_boundbingBox.WestLon <= 180
&& m_boundbingBox.EastLon >= -180
&& m_boundbingBox.EastLon <= 180
&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0
&& m_boundbingBox.SouthLat >= -90
&& m_boundbingBox.SouthLat <= 90
&& m_boundbingBox.NorthLat >= -90
&& m_boundbingBox.NorthLat <= 90)
{
double LonResolution = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / m_SrcFrame->width;
double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;
m_imgPixel_LBH_Coordinate.x = (m_boundbingBox.WestLon + m_imgPixel_XY_Coordinate.x * LonResolution);
m_imgPixel_LBH_Coordinate.y = (m_boundbingBox.NorthLat - m_imgPixel_XY_Coordinate.y * LatResolution);
// 修正
m_imgPixel_LBH_Coordinate.x += (m_deltaLon);
m_imgPixel_LBH_Coordinate.y += (m_deltaLat);
CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";
float fDem = 0;
GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
m_imgPixel_LBH_Coordinate.z = fDem;
}
else
{
m_imgPixel_LBH_Coordinate.x = -200.0;
m_imgPixel_LBH_Coordinate.y = -200.0;
m_imgPixel_LBH_Coordinate.z = -200.0;
}
}
}
else
{
// 设置为 小于0 的无效值
m_imgPixel_XY_Coordinate.x = -1;
m_imgPixel_XY_Coordinate.y = -1;
m_imgPixel_LBH_Coordinate.x = -200.0;
m_imgPixel_LBH_Coordinate.y = -200.0;
m_imgPixel_LBH_Coordinate.z = -200.0;
}
// 定位标记
if (m_iImgEditType == 0)
{
m_bHaveOnPt = false; // 清零
m_bEnhanceEdit = true; // 增强
}
else if (m_iImgEditType == 1) // 定位标记
{
m_bEnhanceEdit = false; // 编辑
// 未作任何处理
if (m_LatestQBData.image.dstImg.buff == NULL/* && m_midImg.buff == NULL*/)
{
CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);
CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
TagLocationOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y),
m_imgPixel_LBH_Coordinate.x,
m_imgPixel_LBH_Coordinate.y,
m_imgPixel_LBH_Coordinate.z);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else
if (srcFrameMat.type() == CV_8UC3
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
TagLocationOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y),
m_imgPixel_LBH_Coordinate.x,
m_imgPixel_LBH_Coordinate.y,
m_imgPixel_LBH_Coordinate.z);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else
if (srcFrameMat.type() == CV_8UC3
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
}
else if (m_iImgEditType == 2) // 文字标记
{
m_bEnhanceEdit = false; // 编辑
CAddTextDlg addTextDlg;
if (addTextDlg.DoModal() == IDOK)
{
CString inputText = addTextDlg.GetText();
// 未作任何处理
if (m_LatestQBData.image.dstImg.buff == NULL/* && m_midImg.buff == NULL*/)
{
CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);
CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
TagTextOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y), inputText);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else
if (srcFrameMat.type() == CV_8UC3
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
TagTextOnImgStru(m_LatestQBData.image.dstImg, cv::Point(m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y), inputText);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else
if (srcFrameMat.type() == CV_8UC3
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
}
}
else if (m_iImgEditType == 3) // 火炮校射标记
{
m_bEnhanceEdit = false; // 编辑
if (m_bHaveOnPt == false)
{
m_bHaveOnPt = true;
m_beginPixPt.x = m_LButtonDblClkPixelCoordinate.x;
m_beginPixPt.y = m_LButtonDblClkPixelCoordinate.y;
m_beginLLA[0] = m_imgPixel_LBH_Coordinate.x;
m_beginLLA[1] = m_imgPixel_LBH_Coordinate.y;
m_beginLLA[2] = m_imgPixel_LBH_Coordinate.z;
}
else
{
m_bHaveOnPt = false;
m_endPixPt.x = m_LButtonDblClkPixelCoordinate.x;
m_endPixPt.y = m_LButtonDblClkPixelCoordinate.y;
m_endLLA[0] = m_imgPixel_LBH_Coordinate.x;
m_endLLA[1] = m_imgPixel_LBH_Coordinate.y;
m_endLLA[2] = m_imgPixel_LBH_Coordinate.z;
// 未作任何处理
if (m_LatestQBData.image.dstImg.buff == NULL/* && m_midImg.buff == NULL*/)
{
CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);
CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
TagInfoReviseShotOnImgStru(m_LatestQBData.image.dstImg, m_beginPixPt, m_endPixPt, m_beginLLA, m_endLLA);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else
if (srcFrameMat.type() == CV_8UC3
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
TagInfoReviseShotOnImgStru(m_LatestQBData.image.dstImg, m_beginPixPt, m_endPixPt, m_beginLLA, m_endLLA);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else
if (srcFrameMat.type() == CV_8UC3
&& srcFrameMat.data != NULL
&& m_LatestQBData.image.dstImg.buff != NULL
&& srcFrameMat.cols > 0 && srcFrameMat.rows > 0
&& srcFrameMat.cols * srcFrameMat.rows < 1e8)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
}
}
else
{
m_bEnhanceEdit = true; // 增强
}
// 回调输出信息即可
if (m_lpSendPixInfoProc != NULL)
{
CPoint pt;
pt.x = m_imgPixel_XY_Coordinate.x;
pt.y = m_imgPixel_XY_Coordinate.y;
m_lpSendPixInfoProc(pt, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, m_imgPixel_LBH_Coordinate.z);
}
}
else
{
// 设置为 小于0 的无效值
m_LButtonDblClkPixelCoordinate.x = -1;
m_LButtonDblClkPixelCoordinate.y = -1;
}
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能:获取当前图像中心的经纬度坐标
bool CImgShowDlg::GetCurrentImgCenterLonLat(double &lon, double &lat)
{
try
{
if (m_SrcFrame == NULL)
{
return false;
}
// 经纬度坐标
double Lon = 0.0;
double Lat = 0.0;
double H = 0;
if (true == DoCalImgCenterCoordinate(Lon, Lat, H, &m_LatestQBData.framePart))
{
lon = Lon + m_deltaLon;
lat = Lat + m_deltaLat;
return true;
}
else
{
if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0
&& m_boundbingBox.WestLon >= -180
&& m_boundbingBox.WestLon <= 180
&& m_boundbingBox.EastLon >= -180
&& m_boundbingBox.EastLon <= 180
&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0
&& m_boundbingBox.SouthLat >= -90
&& m_boundbingBox.SouthLat <= 90
&& m_boundbingBox.NorthLat >= -90
&& m_boundbingBox.NorthLat <= 90)
{
lon = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / 2 + m_boundbingBox.WestLon;
lat = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / 2 + m_boundbingBox.SouthLat;
return true;
}
}
return false;
}
catch(cv::Exception &e)
{
e.msg;
return false;
}
catch(...)
{
return false;
}
}
// 鼠标移动消息响应
void CImgShowDlg::OnMouseMove(UINT nFlags, CPoint point)
{
try
{
CDialog::OnMouseMove(nFlags, point);
if (nFlags == MK_LBUTTON) // 首要条件:左键按下
{
// 如果有外部信号输入 操作与视频模式相同
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
if(m_bSatisfyMove == TRUE)
{
// 更新偏移量
m_ImgShowShift.x += (point.x - m_LeftButtonDown.x);
m_ImgShowShift.y += (point.y - m_LeftButtonDown.y);
// 更新鼠标左键按下点
m_LeftButtonDown = point;
}
return;
}
// 满足图像漫游条件
if(m_bStaisfyRoamImg == TRUE)
{
// 图像未全部显示
if (m_ShowRegion.Width() < m_SrcFrame->width - 1 || m_ShowRegion.Height() < m_SrcFrame->height - 1)
{
// 策略1更新显示区域
int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;
// 像素坐标偏移量
int delatX = int((point.x - m_LeftButtonDown.x) * ratioW);
int delatY = int((point.y - m_LeftButtonDown.y) * ratioH);
m_LeftButtonDown = point;
// 计算显示区域
CRect new_ShowRegion = GetNewRegionWhenRoamImg(delatX, delatY);
// 如果有显示区域变动
if( new_ShowRegion.left - m_ShowRegion.left != 0 ||
new_ShowRegion.right - m_ShowRegion.right != 0 ||
new_ShowRegion.top - m_ShowRegion.top != 0 ||
new_ShowRegion.bottom - m_ShowRegion.bottom != 0)
{
// 更新显示区域
m_ShowRegion = new_ShowRegion;
// 图像显示拉伸比例控制
m_ImgRatioOnScreen = 1.0F;
// 显示图像
ShowOneImage(m_SrcFrame, TRUE, m_ShowRegion, m_ImgRatioOnScreen, m_ImgShowShift);
// 更新标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate),FALSE);
}
}
else
{
// 策略2图像已经全部显示
// 更新偏移量
m_ImgShowShift.x += (point.x - m_LeftButtonDown.x);
m_ImgShowShift.y += (point.y - m_LeftButtonDown.y);
// 更新鼠标左键按下点
m_LeftButtonDown = point;
// 显示图像
ShowWholeImage(m_SrcFrame, m_ImgRatioOnScreen, m_ImgShowShift);
// 更新标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);
}
}
}
// 已经有一个点了
if ((m_bGetTgtImgOn == true || m_bClipImgOn == true)&& m_haveValidFirstPt == TRUE)
{
// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
(point.y > m_ShowRegionOnScreen.top) && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
{
m_clipImgSecondPtScreen = point;
// 重新计算第一个点的屏幕坐标
m_clipImgFirstPtScreen = GetScreenCoordinateBasedOnPixelCoordinate(m_clipImgFirstPt);
CDC* pDC = this->GetDC();
CPen newPen1; // 创建新画笔
newPen1.CreatePen(PS_SOLID, 2, RGB(0, 255, 255));
// 显示区域的地理边界
CRect rect;
GetClientRect(&rect);
InvalidateRect(&rect, FALSE);
UpdateWindow();
CPen *pOldPen = pDC->SelectObject(&newPen1);
CPoint pts[4];
pts[0] = m_clipImgFirstPtScreen;
pts[1].x = m_clipImgSecondPtScreen.x;
pts[1].y = m_clipImgFirstPtScreen.y;
pts[2] = m_clipImgSecondPtScreen;
pts[3].x = m_clipImgFirstPtScreen.x;
pts[3].y = m_clipImgSecondPtScreen.y;
pDC->MoveTo(pts[0]);
pDC->LineTo(pts[1]);
pDC->LineTo(pts[2]);
pDC->LineTo(pts[3]);
pDC->LineTo(pts[0]);
// 释放设备上下文指针
ReleaseDC(pDC);
pDC = NULL;
}
}
//新增功能:计算当前图像 像素坐标 经纬度坐标 RGB值 回调输出
if (m_bFirstSignal == FALSE && m_bSecondSignal == FALSE && m_SrcFrame != NULL && m_bPlotRect == FALSE)
{
// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
(point.y > m_ShowRegionOnScreen.top) && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
{
int ShowRegionWidth = m_ShowRegionOnScreen.Width() + 1;
int ShowRegionHeight = m_ShowRegionOnScreen.Height() + 1;
double ratioW = double(m_ShowRegion.Width() + 1) / ShowRegionWidth;
double ratioH = double(m_ShowRegion.Height() + 1) / ShowRegionHeight;
m_imgPixel_XY_Coordinate.x = static_cast<int>((point.x - m_ShowRegionOnScreen.left) * ratioW + 0.5 + m_ShowRegion.left);
m_imgPixel_XY_Coordinate.y = static_cast<int>((point.y - m_ShowRegionOnScreen.top) * ratioH + 0.5 + m_ShowRegion.top);
// 经纬度坐标
double Lon = 0.0;
double Lat = 0.0;
double H = 0;
if (true == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, m_imgPixel_XY_Coordinate.x, m_imgPixel_XY_Coordinate.y))
{
m_imgPixel_LBH_Coordinate.x = Lon + m_deltaLon;
m_imgPixel_LBH_Coordinate.y = Lat + m_deltaLat;
CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";
float fDem = 0;
GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
m_imgPixel_LBH_Coordinate.z = fDem;
}
else
{
if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0
&& m_boundbingBox.WestLon >= -180
&& m_boundbingBox.WestLon <= 180
&& m_boundbingBox.EastLon >= -180
&& m_boundbingBox.EastLon <= 180
&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0
&& m_boundbingBox.SouthLat >= -90
&& m_boundbingBox.SouthLat <= 90
&& m_boundbingBox.NorthLat >= -90
&& m_boundbingBox.NorthLat <= 90)
{
double LonResolution = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / m_SrcFrame->width;
double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;
m_imgPixel_LBH_Coordinate.x = (m_boundbingBox.WestLon + m_imgPixel_XY_Coordinate.x * LonResolution);
m_imgPixel_LBH_Coordinate.y = (m_boundbingBox.NorthLat - m_imgPixel_XY_Coordinate.y * LatResolution);
// 修正
m_imgPixel_LBH_Coordinate.x += (m_deltaLon);
m_imgPixel_LBH_Coordinate.y += (m_deltaLat);
CString DEMpath = GetSoftwareCurrentDirectory() + "\\ElevationData";
float fDem = 0;
GetElevation(fDem, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, DEMpath.GetBuffer(0));
m_imgPixel_LBH_Coordinate.z = fDem;
}
else
{
m_imgPixel_LBH_Coordinate.x = -200.0;
m_imgPixel_LBH_Coordinate.y = -200.0;
m_imgPixel_LBH_Coordinate.z = -200.0;
}
}
}
else
{
// 设置为 小于0 的无效值
m_imgPixel_XY_Coordinate.x = -1;
m_imgPixel_XY_Coordinate.y = -1;
m_imgPixel_LBH_Coordinate.x = -200.f;
m_imgPixel_LBH_Coordinate.y = -200.f;
m_imgPixel_LBH_Coordinate.z = -200.f;
}
// 回调输出信息即可
if (m_lpSendPixInfoProc != NULL)
{
CPoint pt;
pt.x = m_imgPixel_XY_Coordinate.x;
pt.y = m_imgPixel_XY_Coordinate.y;
m_lpSendPixInfoProc(pt, m_imgPixel_LBH_Coordinate.x, m_imgPixel_LBH_Coordinate.y, m_imgPixel_LBH_Coordinate.z);
}
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 滚轮消息响应
BOOL CImgShowDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
try
{
// 放大
if (zDelta > 0)
{
if (m_SrcFrame != NULL)
{
// 放大并显示图像
DoZoomInImg();
// 更新标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);
}
}else // 缩小
{
if (m_SrcFrame != NULL)
{
// 放大并显示图像
DoZoomOutImg();
// 更新标绘窗口
DrawSquareOnScreen(GetScreenCoordinateBasedOnPixelCoordinate(m_LButtonDblClkPixelCoordinate), FALSE);
}
}
return TRUE;
}
catch(cv::Exception &e)
{
e.msg;
return FALSE;
}
catch(...)
{
return FALSE;
}
}
BOOL CImgShowDlg::OnInitDialog()
{
try
{
CDialog::OnInitDialog();
// 数据存储目录
m_sRootFolder = GetSoftwareCurrentDirectory() + "\\QB_RESULT";
m_sImgSaveFolder = m_sRootFolder + "\\EDITED_IMAGE";
// 创建文件夹
CreateDirectory(m_sRootFolder, NULL);
CreateDirectory(m_sImgSaveFolder, NULL);
m_hMutex_ProcessData = CreateMutexA(NULL, FALSE, NULL);
m_pFastLookUpDlg = new CFastLookUpDlg();
if (m_pFastLookUpDlg != NULL)
{
m_pFastLookUpDlg->Create(IDD_DLG_FAST_LOOKUP_IMGS, this);
m_pFastLookUpDlg->SetParentPt(this);
}
return TRUE;
}
catch(cv::Exception &e)
{
e.msg;
return FALSE;
}
catch(...)
{
return FALSE;
}
}
// 设置一路信号是否正在输入
void CImgShowDlg::SetFirstSignal(BOOL bflag)
{
m_bFirstSignal = bflag;
}
BOOL CImgShowDlg::GetFirstSignal()
{
return m_bFirstSignal;
}
// 设置2路信号是否正在输入
void CImgShowDlg::SetSecondSignal(BOOL bflag)
{
m_bSecondSignal = bflag;
}
BOOL CImgShowDlg::GetSecondSignal()
{
return m_bSecondSignal;
}
// 释放m_LatestQBData
void CImgShowDlg::ReleaseLatestQBData()
{
try
{
ReleaseQBData(&m_LatestQBData);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 设置m_LatestQBData
void CImgShowDlg::SetLatestQBData(const QBStru &qbData)
{
try
{
ReleaseQBData(&m_LatestQBData);
CloneQBData(qbData, m_LatestQBData);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 设置经纬度盒子
void CImgShowDlg::SetBoundingBox(GeoBoundingBox box)
{
m_boundbingBox = box;
}
// 设置iLatest
void CImgShowDlg::SetiLatest(int i)
{
m_iLatest = i;
}
int CImgShowDlg::GetiLatest()
{
return m_iLatest;
}
// 设置iPreLatest
void CImgShowDlg::SetiPreLatest(int i)
{
m_iPreLatest = i;
}
int CImgShowDlg::GetiPreLatest()
{
return m_iPreLatest;
}
//功能:解压后的情报数据处理函数(包括三项:更新本地情报、显示、入队列和对外传递数据)
void CImgShowDlg::DisposeQBData(const QBStru* qbData)
{
try
{
// 空值判断
if (qbData == nullptr)
{
return;
}
// 输入数据有效性判断 如果复接数据和图像数据均无效,直接返回
if ((qbData->framePart.bValid == false) && (qbData->image.bValid == false))
{
return;
}
// 功能1更新数据 m_LatestQBData
CloneQBData(*qbData, m_LatestQBData);
// 设置为 小于0 的无效值
m_LButtonDblClkPixelCoordinate.x = -1;
m_LButtonDblClkPixelCoordinate.y = -1;
// 功能2显示显示图像和 指北针 dstImg 或 srcImg不显示geoImg暂时觉得没必要
ShowLatestQBData();
// 功能3入队列: 按需入队
if (m_bMemPreMultiFrame == TRUE)
{
PushLatestQBData2Deque();
// 功能4送入 快速查询模块
if (m_pFastLookUpDlg != NULL)
{
m_pFastLookUpDlg->SetImgData(m_LatestQBData.image.srcImg);
if (m_pFastLookUpDlg->IsWindowVisible() == TRUE)
{
m_pFastLookUpDlg->ShowImgData();
}
}
}
// 更新数目,注意不是+1
WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
m_currentImgOrder = static_cast<int>(m_QBDataDeque.size());
ReleaseMutex(m_hMutex_ProcessData);
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 功能m_LatestQBData 入队列
// 输入:
// 输出:
// 说明只有当m_LatestQBData图像数据有效时方可入队
// 功能LatestQBData 入队列,
void CImgShowDlg::PushLatestQBData2Deque()
{
WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
try
{
if (m_LatestQBData.image.bValid == true) // 图像数据有效
{
if ( m_QBDataDeque.size() < 18U)
{
QBStru local; // 局部变量
CloneQBData(m_LatestQBData,local); // 深度复制
m_QBDataDeque.push_back(local); // 入队,浅复制
// 设置局部变量buffer指向空否则local超出作用域会析构其指向的内存单元
// 从而使local中已入队的结构体成为野指针
local.image.srcImg.buff = NULL;
local.image.dstImg.buff = NULL;
local.image.geoImg.buff = NULL;
}
else
{
while(m_QBDataDeque.size() >= 18U) // 设计原因:中途可能设置小于当前数目的容量
{
// 弹出
std::deque<QBStru>::iterator iter; // 定义迭代器
iter = m_QBDataDeque.begin();
// 释放指针指向的内存
SAFE_DELETE_ARRAY(iter->image.srcImg.buff);
SAFE_DELETE_ARRAY(iter->image.dstImg.buff);
SAFE_DELETE_ARRAY(iter->image.geoImg.buff);
// 弹出
m_QBDataDeque.pop_front();
}
// 当前帧入队
QBStru local; // 局部变量
CloneQBData(m_LatestQBData, local); // 深度复制
m_QBDataDeque.push_back(local); // 入队,浅复制
// 设置局部变量buffer指向空否则local超出作用域会析构其指向的内存单元
// 从而使local中已入队的结构体成为野指针
local.image.srcImg.buff = NULL;
local.image.dstImg.buff = NULL;
local.image.geoImg.buff = NULL;
}
}
}
catch(cv::Exception &e)
{
e.msg;
}
catch(...)
{
}
ReleaseMutex(m_hMutex_ProcessData);
}
// 1.29 功能:清理内存及记忆
// 输入:无
//
// 输出:无
void CImgShowDlg::ClearMemory()
{
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
return;
}
try
{
// 如果有图像 需要释放该图像
if (m_SrcFrame != NULL)
{
cvReleaseImage(&m_SrcFrame);
m_SrcFrame = NULL;
}
// 当前情报数据结构体:LatestQBData
ReleaseQBData(&m_LatestQBData);
WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
// 情报队列销毁
if(m_QBDataDeque.size() > 0)
{
for (size_t i = 0; i < m_QBDataDeque.size(); ++i)
{
SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.srcImg.buff);
SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.dstImg.buff);
SAFE_DELETE_ARRAY(m_QBDataDeque[i].image.geoImg.buff);
}
m_QBDataDeque.clear();
}
ReleaseMutex(m_hMutex_ProcessData);
// midImg 释放
SAFE_DELETE_ARRAY(m_midImg.buff);
// 复位
m_ShowRegion = CRect(0,0,0,0);
m_ShowRegionOnScreen.left = 0;
m_ShowRegionOnScreen.right = 0;
m_ShowRegionOnScreen.top = 0;
m_ShowRegionOnScreen.bottom = 0;
m_LButtonDownPixelCoordinate = CPoint(0,0);
m_bStaisfyRoamImg = FALSE;
m_LatestPlotRect = CRect(0,0,0,0);
m_LButtonDblClkPixelCoordinate = CPoint(-1, -1);
m_LeftButtonDown.x = 0;
m_LeftButtonDown.y = 0;
m_RButtonPt.x = 0;
m_RButtonPt.y = 0;
m_SrcFrame = NULL;
m_ImgRatioOnScreen = 1.0F;
m_ImgShowShift.x = 0L;
m_ImgShowShift.y = 0L;
m_bFirstSignal = FALSE;
m_bSecondSignal = FALSE;
m_bSatisfyMove = FALSE;
m_iLatest = 0;
m_iPreLatest = 0;
m_LatestQuadrangle = CRect(0,0,0,0);
// 像素信息
m_imgPixel_XY_Coordinate.x = -1;
m_imgPixel_XY_Coordinate.y = -1;
m_imgPixel_LBH_Coordinate.x = -200.0;
m_imgPixel_LBH_Coordinate.y = -200.0;
m_imgPixel_LBH_Coordinate.z = -200.0;
m_currentImgOrder = 0;
m_TargetCenter = cv::Point(-100, -100);
m_bDrawSquareOnImg = TRUE;
m_deltaLon = 0;
m_deltaLat = 0;
// 使窗口无效
Invalidate();
// 释放快速浏览对话框内存图像
if (m_pFastLookUpDlg != NULL)
{
m_pFastLookUpDlg->ClearMemory();
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 3.12 功能保存图像为tiff并回调保存路径
// 说明当保存为tiff图像时忽略校准量牵扯面太广且不可靠
// 如果实在想高精度保存一幅图像为tiff,可通过GCP几何校正实现
void CImgShowDlg::SaveToGeoTiff()
{
try
{
// 计算保存路径
CString savePath;
CString sRootFolder;
CString sImgSaveFolder;
// 数据存储目录
sRootFolder = GetSoftwareCurrentDirectory() + "\\QB_RESULT";
sImgSaveFolder = sRootFolder + "\\EDITED_IMAGE";
// 创建文件夹
CreateDirectory(sRootFolder, NULL);
CreateDirectory(sImgSaveFolder, NULL);
// 计算存储路径
SYSTEMTIME CurrentTime;
GetLocalTime(&CurrentTime);
savePath.Format( "%04d%02d%02d_%02d%02d%02d%04d",
CurrentTime.wYear,
CurrentTime.wMonth,
CurrentTime.wDay,
CurrentTime.wHour,
CurrentTime.wMinute,
CurrentTime.wSecond,
CurrentTime.wMilliseconds);
savePath = "Geo_" + savePath;
savePath = savePath + _T(".tif");
savePath = sImgSaveFolder + "\\" + savePath;
bool bret = false;
// 保存为tiff
if (true == SaveToGeoTIFF(&m_LatestQBData, savePath.GetBuffer(0)))
{
bret = true;
}
else if (true == SaveToGeoTIFF(&m_LatestQBData.image.dstImg, savePath.GetBuffer(0)))
{
bret = true;
}
else if (true == SaveToGeoTIFF(&m_LatestQBData.image.srcImg, savePath.GetBuffer(0)))
{
bret = true;
}
else
{
bret = false;
}
if (bret == true)
{
// 保存路径回调
if (m_lpSendFilePath != NULL)
{
m_lpSendFilePath(savePath, 6);
}
}
// 清理 geoImg
SAFE_DELETE_ARRAY(m_LatestQBData.image.geoImg.buff);
m_LatestQBData.image.geoImg.buff = NULL;
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 右键 清理内存记忆
void CImgShowDlg::OnClearMemory()
{
try
{
ClearMemory();
// 复位目标标绘
m_bPlotRect = FALSE;
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 单帧校正采集
void CImgShowDlg::OnSaveImgToTiff()
{
SaveToGeoTiff();
}
// 功能:图像去雾
void CImgShowDlg::AdjustImgDehaze(BOOL bAdjust, int A_MAX, double degree)
{
try
{
if (bAdjust == TRUE)
{
if(m_bEnhanceEdit == true) // 增强
{
if (GetiLatest() == 0) // 如果刚什么也没做
{
if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
{
CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(1);
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(1);
}
}
else if (GetiLatest() == 1) // 如果刚才就是去雾
{
DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX,degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
}
else // 其它
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
DoDehazeCtrl(&m_midImg, &m_LatestQBData.image.dstImg, A_MAX,degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(1);
}
}
}
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 功能:图像亮度调节
void CImgShowDlg::AdjustImgIntensity(BOOL bAdjust, int degree)
{
try
{
// 执行亮度调节
if(bAdjust == TRUE)
{
if (degree == 10)
{
return;
}
if (m_bEnhanceEdit == true) // 增强
{
if (GetiLatest() == 0)
{
if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
{
CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(2);
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(2);
}
}
else if(GetiLatest() == 2)
{
DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
DoIntensityCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(2);
}
}
}
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 功能:图像对比度调节
void CImgShowDlg::AdjustImgContrast(BOOL bAdjust, int degree)
{
try
{
if(bAdjust == TRUE)
{
if (degree == 10)
{
return;
}
if (m_bEnhanceEdit == true) // 增强
{
if (GetiLatest() == 0)
{
if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
{
CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(3);
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(3);
}
}
else if(GetiLatest() == 3)
{
DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
DoContrastCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(3);
}
}
}
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 功能:图像清晰度调节
void CImgShowDlg::AdjustImgDefinition(BOOL bAdjust, int degree)
{
try
{
if(bAdjust == TRUE)
{
if (degree == 10)
{
return;
}
if (m_bEnhanceEdit == true) // 增强
{
if (GetiLatest() == 0)
{
if (m_LatestQBData.image.dstImg.buff == NULL && m_midImg.buff == NULL)
{
CloneImgStru(m_LatestQBData.image.srcImg,m_midImg);
DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(4);
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg,m_midImg);
DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(4);
}
}
else if(GetiLatest() == 4)
{
DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
}
else
{
CloneImgStru(m_LatestQBData.image.dstImg, m_midImg);
DoDefinitionCtrl(&m_midImg, &m_LatestQBData.image.dstImg, degree);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
SetiPreLatest(GetiLatest());
SetiLatest(4);
}
}
}
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 功能:返回图像调节上一步图像状态
void CImgShowDlg::ReturnToPreImgState()
{
try
{
if (m_bEnhanceEdit == true)
{
CloneImgStru(m_midImg, m_LatestQBData.image.dstImg);
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
// 返回一步
SetiLatest(GetiPreLatest());
}
else
{
CloneImgStru(m_midImg, m_LatestQBData.image.dstImg);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else if (srcFrameMat.type() == CV_8UC3)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.dstImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 功能:返回原始图像状态
void CImgShowDlg::ReturnToSrcImgState()
{
try
{
if (m_bEnhanceEdit == true)
{
SAFE_DELETE_ARRAY(m_midImg.buff);
m_midImg.buff = NULL;
SAFE_DELETE_ARRAY(m_LatestQBData.image.dstImg.buff);
m_LatestQBData.image.dstImg.buff = NULL;
ShowLatestQBData(); // 显示图像
SetTargetPixelCoordinate(GetTargetCoordinate());
// 一步还原
SetiLatest(0);
SetiPreLatest(0);
}
else
{
CloneImgStru(m_LatestQBData.image.srcImg, m_midImg);
CloneImgStru(m_LatestQBData.image.srcImg, m_LatestQBData.image.dstImg);
// 标记 m_SrcFrame
cv::Mat srcFrameMat(m_SrcFrame, false);
if (srcFrameMat.type() == CV_8UC1)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.srcImg.buff, srcFrameMat.cols * srcFrameMat.rows); // 图像数据复制
}
else if (srcFrameMat.type() == CV_8UC3)
{
memcpy(srcFrameMat.data, m_LatestQBData.image.srcImg.buff, srcFrameMat.cols * srcFrameMat.rows * 3); // 图像数据复制
}
Invalidate();
}
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 18 功能:设置图像编辑类型
void CImgShowDlg::SetImgEditType(int type)
{
m_iImgEditType = type;
if (type == 1 || type == 2 || type == 3)
{
m_bEnhanceEdit = false;
}
else
{
m_bEnhanceEdit = true;
}
}
// 获取图像编辑模式 true 增强 false 标记
bool CImgShowDlg::GetImgEditMode()
{
return m_bEnhanceEdit;
}
// 20 功能:显示记忆图像队列中的指定某一张图像
void CImgShowDlg::ShowSelectedImgInMem(int order)
{
WaitForSingleObject(m_hMutex_ProcessData, INFINITE);
try
{
if (m_QBDataDeque.empty() == false)
{
if (order >= 1 && order <= static_cast<int>(m_QBDataDeque.size())/* && m_currentImgOrder != order*/)
{
// 释放
ReleaseQBData(&m_LatestQBData);
SAFE_DELETE(m_midImg.buff);
m_midImg.buff = NULL;
CloneQBData(m_QBDataDeque[order - 1], m_LatestQBData);
ShowLatestQBData();
m_currentImgOrder = order;
}
}
}
catch(cv::Exception &e)
{
e.what();
}
catch (...)
{
int a = 8;
}
ReleaseMutex(m_hMutex_ProcessData);
}
// 快速查找图像
void CImgShowDlg::OnFastLookupImgs()
{
try
{
if (m_pFastLookUpDlg != NULL)
{
// 为空时
if (m_pFastLookUpDlg->isEmpty() == true)
{
::MessageBoxA(NULL, _T("无记忆图像供查找!"),_T("操作提示"), MB_OK);
m_pFastLookUpDlg->ShowWindow(SW_HIDE);
return;
}
else
{
if (TRUE == m_pFastLookUpDlg->IsWindowVisible())
{
m_pFastLookUpDlg->ShowWindow(SW_HIDE);
}
else
{
m_pFastLookUpDlg->ShowWindow(SW_SHOW);
m_pFastLookUpDlg->ShowImgData();
}
}
}
}
catch(cv::Exception &e)
{
e.what();
return;
}
catch (...)
{
return;
}
}
// 定位引导
void CImgShowDlg::OnTgtLocLead()
{
try
{
// 右键坐标
CPoint point;
point.x = m_RButtonPt.x;
point.y = m_RButtonPt.y;
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
return;
}
if (m_SrcFrame != NULL)
{
// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
(point.y > m_ShowRegionOnScreen.top) && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
{
// 图像尺寸与显示区域尺寸之间的比例
double ratio = 1.0;
// 分母0值判断
if (m_ShowRegionOnScreen.Width() > 0)
{
ratio = (m_ShowRegion.Width() * 1.0) / m_ShowRegionOnScreen.Width();
}
CPoint PixelCoordinate; // 像素坐标
PixelCoordinate.x = static_cast<LONG>((point.x - m_ShowRegionOnScreen.left) * ratio) + m_ShowRegion.left;
PixelCoordinate.y = static_cast<LONG>((point.y - m_ShowRegionOnScreen.top) * ratio) + m_ShowRegion.top;
// 经纬度坐标
double Lon = -200;
double Lat = -200;
double H = 0;
// 图像四个顶点的经纬度坐标
double Lon1 = -200, Lat1 = -200, H1 = -200;
double Lon2 = -200, Lat2 = -200, H2 = -200;
double Lon3 = -200, Lat3 = -200, H3 = -200;
double Lon4 = -200, Lat4 = -200, H4 = -200;
if (false == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, PixelCoordinate.x, PixelCoordinate.y))
{
if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0
&& m_boundbingBox.WestLon >= -180
&& m_boundbingBox.WestLon <= 180
&& m_boundbingBox.EastLon >= -180
&& m_boundbingBox.EastLon <= 180
&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0
&& m_boundbingBox.SouthLat >= -90
&& m_boundbingBox.SouthLat <= 90
&& m_boundbingBox.NorthLat >= -90
&& m_boundbingBox.NorthLat <= 90)
{
double LonResolution = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / m_SrcFrame->width;
double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;
Lon = float(m_boundbingBox.WestLon + PixelCoordinate.x * LonResolution);
Lat = float(m_boundbingBox.NorthLat - PixelCoordinate.y * LatResolution);
// 四个角点经纬度
Lon1 = m_boundbingBox.WestLon, Lat1 = m_boundbingBox.NorthLat;
Lon2 = m_boundbingBox.EastLon, Lat2 = m_boundbingBox.NorthLat;
Lon3 = m_boundbingBox.EastLon, Lat3 = m_boundbingBox.SouthLat;
Lon4 = m_boundbingBox.WestLon, Lat4 = m_boundbingBox.SouthLat;
}
else
{
Lon = -200.f;
Lat = -200.f;
}
}
else
{
// 计算四个角点的经纬度坐标
bool ret1 = DoCalAnyPtCoordinate(Lon1, Lat1, H1, &m_LatestQBData.framePart, 0, 0);
bool ret2 = DoCalAnyPtCoordinate(Lon2, Lat2, H2, &m_LatestQBData.framePart, m_SrcFrame->width - 1, 0);
bool ret3 = DoCalAnyPtCoordinate(Lon3, Lat3, H3, &m_LatestQBData.framePart, m_SrcFrame->width - 1, m_SrcFrame->height - 1);
bool ret4 = DoCalAnyPtCoordinate(Lon4, Lat4, H4, &m_LatestQBData.framePart, 0, m_SrcFrame->height - 1);
}
// 修正
if (abs(Lon) < 180 && abs(Lat) < 90)
{
Lon += m_deltaLon;
Lat += m_deltaLat;
Lon1 += m_deltaLon, Lat1 += m_deltaLat;
Lon2 += m_deltaLon, Lat2 += m_deltaLat;
Lon3 += m_deltaLon, Lat3 += m_deltaLat;
Lon4 += m_deltaLon, Lat4 += m_deltaLat;
}
// 回调输出
if (m_lpSendTgrLocLeadLonLat != NULL)
{
m_lpSendTgrLocLeadLonLat(Lon, Lat,
Lon1, Lat1,
Lon2, Lat2,
Lon3, Lat3,
Lon4, Lat4);
}
}
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
void CImgShowDlg::LeadImgLoc()
{
CRect rect;
GetClientRect(&rect);
// 右键坐标
m_RButtonPt.x = rect.Width() / 2;
m_RButtonPt.y = rect.Height() / 2;
OnTgtLocLead();
}
// 几何校正 并显示图像
void CImgShowDlg::OnGeoCorrectAndShow()
{
try
{
// 当未设置定位导引输出函数指针时,即不用于地图匹配定位时,该功能设为无效
if (m_lpSendTgrLocLeadLonLat == NULL)
{
return;
}
// 几何校正: 选择该模式的原因是牵扯到图像增强等操作
if (TRUE == DoSysGeoCorrect(&m_LatestQBData))
{
SAFE_DELETE_ARRAY(m_LatestQBData.image.srcImg.buff);
SAFE_DELETE_ARRAY(m_LatestQBData.image.dstImg.buff);
CloneImgStru(m_LatestQBData.image.geoImg, m_LatestQBData.image.srcImg);
SAFE_DELETE_ARRAY(m_LatestQBData.image.geoImg.buff);
// 复接数据设置为0 无效
m_LatestQBData.framePart.bValid = false;
memset(&m_LatestQBData.framePart, 0, sizeof(m_LatestQBData.framePart));
// 设置经纬度盒子
SetBoundingBox(m_LatestQBData.image.srcImg.BoundingBox);
// 显示图像
ShowLatestQBData();
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch (...)
{
return;
}
}
// 设置文件夹
void CImgShowDlg::SetSaveCurrentImgFolder(CString str)
{
m_sSaveCurrentImgFolder = str;
}
void CImgShowDlg::SetSavePreMultiImgFolder(CString str)
{
m_sSavePreMultiImgFolder = str;
}
// 21 功能:几何校正并显示图像
void CImgShowDlg::GeoCorrectAndShowImg()
{
OnGeoCorrectAndShow();
}
// 在图像中标绘目标 矩形 定位用
void CImgShowDlg::OnDrawSqureOnImg()
{
// 只有设置了目标导引情况下操作
if (m_lpSendTgrLocLeadLonLat != NULL)
{
m_bDrawSquareOnImg = !m_bDrawSquareOnImg;
}
else
{
m_bDrawSquareOnImg = FALSE;
}
}
// 图像加载线程(GDAL)
UINT LoadImgThroughGDAL(void *pt)
{
CImgShowDlg *ptr = (CImgShowDlg*)pt;
if (ptr == nullptr)
{
return 0;
}
CString ImgFilePath = ptr->m_GDALLoadImgPath;
try
{
// 注册
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
// 打开图像
GDALDataset* srcDataSet = nullptr;
srcDataSet = (GDALDataset*)GDALOpen(ImgFilePath, GA_ReadOnly);
if (srcDataSet != nullptr)
{
// 获取图像参数
int Width = srcDataSet->GetRasterXSize();
int Height = srcDataSet->GetRasterYSize();
int nBound = srcDataSet->GetRasterCount();
if (nBound == 1 || nBound == 3)
{
double r = 0;
if (Width > Height)
{
r = 10000.0 / Width;
}
else
{
r = 10000.0 / Height;
}
if (r > 1)
{
r = 1.0;
}
int scaledWidth = int(Width * r);;
int scaledHeight = int(Height * r);
if (scaledWidth > 0 && scaledHeight > 0)
{
GDALRasterBand *pBand = srcDataSet->GetRasterBand(1);
GDALDataType type = pBand->GetRasterDataType();
cv::Mat img;
if (nBound == 1)
{
img = cv::Mat(scaledHeight, scaledWidth, CV_8UC1, cv::Scalar(0));
pBand->RasterIO(GF_Read, 0,0, Width, Height, img.data, img.cols, img.rows, type, 0, 0);
}
else
{
img = cv::Mat(scaledHeight, scaledWidth, CV_8UC3, cv::Scalar(0));
int bandMap[3] = {3, 2, 1};
CPLErr error = srcDataSet->RasterIO(GF_Read, 0,0,
Width, Height,
img.data,
img.cols, img.rows,
type,
3,
bandMap,
3, // nPixelSpace
3 * scaledWidth, // nLineSpace
1); // nBandSpace
}
BITMAPINFO info;
info.bmiHeader.biWidth = img.cols;
info.bmiHeader.biHeight = img.rows;
info.bmiHeader.biBitCount = static_cast<WORD>(img.channels() * 8);
double GISDATA[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
srcDataSet->GetGeoTransform(GISDATA);
double WLon = GISDATA[0];
double ELon = GISDATA[0] + Width * GISDATA[1];
double NLat = GISDATA[3];
double SLat = GISDATA[3] + Height * GISDATA[5];
GeoBoundingBox LBbox;
LBbox.WestLon = WLon;
LBbox.EastLon = ELon;
LBbox.SouthLat = SLat;
LBbox.NorthLat = NLat;
ptr->LoadOneImgFromMenu(&info, img.data, LBbox);
}
}
}
GDALClose(srcDataSet);
srcDataSet = NULL;
}
catch(...)
{
return 0;
}
return 0;
}
// 右键打开一副图像
void CImgShowDlg::OnOpenOneImg()
{
CFileDialog ImgDialog(
TRUE,
NULL,
NULL,
OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
_T("Image files (*.bmp;*.jpg;*.tif;) |*.bmp;*.jpg;*.tif;| All Files (*.*) |*.*||"),
NULL);
ImgDialog.m_ofn.lpstrTitle = _T("打开一幅图像");
if (ImgDialog.DoModal() != IDOK)
{
return;
}
CString ImgFilePath = ImgDialog.GetPathName();
m_GDALLoadImgPath = ImgFilePath;
int len = ImgFilePath.GetLength();
int leftLen = ImgFilePath.ReverseFind('.');
CString Type = ImgFilePath.Right(len - leftLen);
std::string path = ImgFilePath.GetString();
try
{
cv::Mat img = cv::imread(path, -1);
if (img.empty() == true)
{
return;
}
else
{
BITMAPINFO info;
info.bmiHeader.biWidth = img.cols;
info.bmiHeader.biHeight = img.rows;
info.bmiHeader.biBitCount = static_cast<WORD>(img.channels() * 8);
if (Type == ".tif")
{
// 读取文件地理信息
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
GDALDataset* tempdata = nullptr;
tempdata = ( GDALDataset* )GDALOpen((LPSTR)(LPCTSTR)ImgFilePath, GA_ReadOnly);
double GISDATA[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
if (tempdata != NULL)
{
tempdata->GetGeoTransform(GISDATA);
// 获取尺寸
int width = tempdata->GetRasterXSize();
int height = tempdata->GetRasterYSize();
double WLon = GISDATA[0];
double ELon = GISDATA[0] + width * GISDATA[1];
double NLat = GISDATA[3];
double SLat = GISDATA[3] + height * GISDATA[5];
GeoBoundingBox LBbox;
LBbox.WestLon = WLon;
LBbox.EastLon = ELon;
LBbox.SouthLat = SLat;
LBbox.NorthLat = NLat;
LoadOneImgFromMenu(&info, img.data, LBbox);
}
else
{
LoadOneImgFromMenu(&info, img.data);
}
GDALClose( tempdata );
tempdata = NULL;
}
else
{
LoadOneImgFromMenu(&info, img.data);
}
}
}
catch(cv::Exception &e)
{
e.what();
::MessageBoxA(NULL, _T("图像过大,缩放显示!"),_T("操作提示"), MB_OK);
// 启动GDAL数据加载线程
AfxBeginThread(LoadImgThroughGDAL, this);
}
catch(...)
{
}
}
void CImgShowDlg::LoadOneImgFromMenu(const BITMAPINFO* pImgInfo,
BYTE* pImgData,
GeoBoundingBox LBbox,
BOOL isNeedFlip,
BOOL isNeedClip,
const CRect* pShowRegion,
float Strecth_Ratio,
POINT xyShift)
{
try
{
// 数据有效性验证
if ( (pImgInfo == NULL) || (pImgData == NULL))
{
return;
}
// 设置一路输入正在输入标识
SetFirstSignal(TRUE);
// biBitCount 验证
if(pImgInfo->bmiHeader.biBitCount != 24 && pImgInfo->bmiHeader.biBitCount != 8)
{
SetFirstSignal(FALSE);
return;
}
// 更新数据至全局变量LatestQBData
if (pImgInfo->bmiHeader.biWidth > 0 &&
pImgInfo->bmiHeader.biHeight > 0 &&
pImgData != NULL)
{
// 设置一路输入正在输入标识
SetFirstSignal(TRUE);
// 构建临时对象
QBStru local;
local.image.srcImg.ImgWidth = pImgInfo->bmiHeader.biWidth;
local.image.srcImg.ImgHeight = pImgInfo->bmiHeader.biHeight;
local.image.srcImg.bitcount = pImgInfo->bmiHeader.biBitCount;
// 步长:每行像素所占字节数
int lineByte = (pImgInfo->bmiHeader.biWidth * pImgInfo->bmiHeader.biBitCount / 8);
// 位图数据缓冲区的大小,即图像大小
int imgBufSize = pImgInfo->bmiHeader.biHeight * lineByte;
if ( imgBufSize > 0)
{
local.image.srcImg.buff = new BYTE[imgBufSize];
if (local.image.srcImg.buff != NULL)
{
// 复制实际字节数
memcpy(local.image.srcImg.buff, pImgData, static_cast<size_t>(imgBufSize)); // 图像数据复制
// 设置图像数据有效
local.image.bValid = true;
// 是否需要反转
if (isNeedFlip == TRUE)
{
FlipImgStru(&local.image.srcImg);
}
}
}
local.image.srcImg.BoundingBox = LBbox;
/*m_boundbingBox = LBbox;*/
// 将 local 复制到 m_LatestQBData
SetLatestQBData(local);
SetBoundingBox(LBbox);
// 释放 local
if (local.image.srcImg.buff != NULL)
{
SAFE_DELETE_ARRAY(local.image.srcImg.buff);
}
// 显示图像
// 接口转换
CRect ShowRegion;
if (pShowRegion != NULL)
{
ShowRegion = *pShowRegion;
}
ShowOneImage(const_cast<BITMAPINFO*>(pImgInfo), pImgData, isNeedClip, ShowRegion, isNeedFlip, Strecth_Ratio, xyShift);
// 图像去雾 亮度调节 对比度调节 清晰度调节 复位
SetiLatest(0); // 最近的一次
SetiPreLatest(0); // 最近的一次的前一次
// 关闭1路正在输入标识
SetFirstSignal(FALSE);
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 单点定位校准
void CImgShowDlg::OnTgtloccalibrate()
{
try
{
CTgtLocCalibrateDlg TLCdlg;
if (TLCdlg.DoModal() == IDOK)
{
// 获取校准值
double calibrateLon = TLCdlg.GetCalibrateLon();
double calibrateLat = TLCdlg.GetCalibrateLat();
if (abs(calibrateLon) > 180 || abs(calibrateLat) > 90)
{
return;
}
// 取消校准
if (abs(calibrateLon) + abs(calibrateLat) < 1e-5)
{
m_deltaLon = 0;
m_deltaLat = 0;
}
// 获取校准前的值
// 经纬度坐标
double Lon = -200;
double Lat = -200;
double H = 0;
// 右键坐标
CPoint point;
point.x = m_RButtonPt.x;
point.y = m_RButtonPt.y;
if (m_bFirstSignal == TRUE || m_bSecondSignal == TRUE)
{
return;
}
if (m_SrcFrame != NULL)
{
// 计算 CPoint point 对应的像素坐标 CPoint LButtonDblClkPixelCoordinate;
if ((point.x > m_ShowRegionOnScreen.left) && (point.x < m_ShowRegionOnScreen.right) &&
(point.y > m_ShowRegionOnScreen.top) && (point.y < m_ShowRegionOnScreen.bottom)) // 鼠标在图像上
{
// 图像尺寸与显示区域尺寸之间的比例
double ratio = 1.0;
// 分母0值判断
if (m_ShowRegionOnScreen.Width() > 0)
{
ratio = (m_ShowRegion.Width() * 1.0) / m_ShowRegionOnScreen.Width();
}
CPoint PixelCoordinate; // 像素坐标
PixelCoordinate.x = static_cast<LONG>((point.x - m_ShowRegionOnScreen.left) * ratio) + m_ShowRegion.left;
PixelCoordinate.y = static_cast<LONG>((point.y - m_ShowRegionOnScreen.top) * ratio) + m_ShowRegion.top;
if (false == DoCalAnyPtCoordinate(Lon, Lat, H, &m_LatestQBData.framePart, PixelCoordinate.x, PixelCoordinate.y))
{
if (m_boundbingBox.EastLon - m_boundbingBox.WestLon > 0
&& m_boundbingBox.WestLon >= -180
&& m_boundbingBox.WestLon <= 180
&& m_boundbingBox.EastLon >= -180
&& m_boundbingBox.EastLon <= 180
&& m_boundbingBox.NorthLat - m_boundbingBox.SouthLat > 0
&& m_boundbingBox.SouthLat >= -90
&& m_boundbingBox.SouthLat <= 90
&& m_boundbingBox.NorthLat >= -90
&& m_boundbingBox.NorthLat <= 90)
{
double LonResolution = (m_boundbingBox.EastLon - m_boundbingBox.WestLon) / m_SrcFrame->width;
double LatResolution = (m_boundbingBox.NorthLat - m_boundbingBox.SouthLat) / m_SrcFrame->height;
Lon = float(m_boundbingBox.WestLon + PixelCoordinate.x * LonResolution);
Lat = float(m_boundbingBox.NorthLat - PixelCoordinate.y * LatResolution);
}
else
{
return;
}
}
}
else
{
return;
}
}
else
{
return;
}
// 计算修正量
double deltaLon = calibrateLon - Lon;
double deltaLat = calibrateLat - Lat;
if (abs(deltaLon) > 1 || abs(deltaLat) > 1)
{
return;
}
else
{
m_deltaLon = deltaLon;
m_deltaLat = deltaLat;
}
}
}
catch(cv::Exception &e)
{
e.msg;
return;
}
catch(...)
{
return;
}
}
// 查看 经纬度校准量
void CImgShowDlg::OnViewDeltaLonLat()
{
// TODO: 在此添加命令处理程序代码
CString sDeltaLon;
sDeltaLon.Format("%.6f", m_deltaLon);
CString sDeltaLat;
sDeltaLat.Format("%.6f", m_deltaLat);
CString msg = "delatLon = " + sDeltaLon + "\n" + "deltaLat = " + sDeltaLat;
::MessageBoxA(NULL, _T(msg), _T("操作提示"), MB_OK);
}
// 22 功能:获取当前显示图像
cv::Mat CImgShowDlg::GetCurrentImg()
{
cv::Mat img;
if (m_SrcFrame != NULL)
{
img = cv::Mat(m_SrcFrame, true);
}
return img;
}
// 24 功能:标注图像(矩形、区域边缘)
// 输入:
// 1. 区域边缘点 集合
void CImgShowDlg::MarkRegionOnImg(std::vector<std::vector<cv::Point>> &valisContours)
{
try
{
if (valisContours.size() > 0)
{
if (m_SrcFrame != NULL && m_SrcFrame->width > 0 && m_SrcFrame->height > 0)
{
cv::Mat img(m_SrcFrame, false);
for (size_t i = 0; i < valisContours.size(); i++)
{
cv::Rect rect = cv::boundingRect(valisContours[i]);
cv::rectangle(img, rect, cv::Scalar(0,255,255), 2);
}
cv::drawContours(img, valisContours, -1, cv::Scalar(0,255,255), 1);
// m_midImg
if (m_LatestQBData.image.dstImg.buff != NULL)
{
memcpy(m_LatestQBData.image.dstImg.buff, img.data, img.cols * img.rows * img.channels());
}
if (m_LatestQBData.image.srcImg.buff != NULL)
{
memcpy(m_LatestQBData.image.srcImg.buff, img.data, img.cols * img.rows * img.channels());
}
ShowLatestQBData();
}
}
}
catch(cv::Exception &e)
{
e.what();
}
catch (...)
{
}
}
// 功能:屏蔽右键按钮菜单
void CImgShowDlg::CloseRightBtnDownMenu(bool bClose)
{
m_bCloseRughtBtnMenu = bClose;
}
// 功能:设置空屏文字
void CImgShowDlg::SetThemeText(CString str)
{
m_sThemeText = str;
}
void CImgShowDlg::OnGetTargetImg()
{
if (m_bClipImgOn == true)
{
m_bGetTgtImgOn = false;
m_haveValidFirstPt = false;
}
else
{
m_bGetTgtImgOn = !m_bGetTgtImgOn;
if (m_bGetTgtImgOn == false)
{
m_haveValidFirstPt = false;
}
}
}
// 功能:获取图像边界地理坐标
bool CImgShowDlg::GetImgBoundingBox(double &leftLon, double &topLat, double &rigtLon, double &bottomLat)
{
double leftLon0 = m_LatestQBData.image.srcImg.BoundingBox.WestLon;
double rigtLon0 = m_LatestQBData.image.srcImg.BoundingBox.EastLon;
double topLat0 = m_LatestQBData.image.srcImg.BoundingBox.NorthLat;
double bottomLat0 = m_LatestQBData.image.srcImg.BoundingBox.SouthLat;
if (abs(leftLon0) <= 180 && abs(rigtLon0) <= 180 && leftLon0 < rigtLon0 &&
abs(topLat0) <= 90 && abs(bottomLat0) <= 90 && bottomLat0 < topLat0)
{
leftLon = leftLon0;
rigtLon = rigtLon0;
topLat = topLat0;
bottomLat = bottomLat0;
return true;
}
else
{
return false;
}
}
void CImgShowDlg::OnClipImg()
{
m_bClipImgOn = !m_bClipImgOn;
if (m_bClipImgOn == true)
{
m_bGetTgtImgOn = false;
}
m_haveValidFirstPt = false;
}