icp配準進度條
icp配準過程太慢了,考慮加個進度條。先在主對話方塊上測試一下進度條的用法,需要用多執行緒來執行。
新建一個類MyThread,標頭檔案:
#pragma once
#include <process.h>
#include <Windows.h>
#define WM_USER_MSG WM_USER + 1001
class MyThread
{
public:
// 執行緒回撥函式必須是全域性函式
static void Run(void *ptr);
public:
MyThread(void);
~MyThread(void);
};
原始檔:
#include "stdafx.h"
#include "MyThread.h"
void MyThread::Run(void *ptr)
{
HWND hWnd = (HWND)ptr;
for (int i = 0; i<105; ++i)
{
::PostMessage(hWnd, WM_USER_MSG, WPARAM(i), LPARAM(0));
Sleep(100);
}
AfxMessageBox(_T("done"));
_endthread();
}
MyThread::MyThread()
{
}
MyThread::~MyThread()
{
}
在主對話方塊上新增一個進度條控制元件,id設定為IDC_PROGRESS。再新增一個按鈕用於觸發進度條,id為IDC_BTN_PROGRESS。
在對話方塊類的標頭檔案宣告一個訊息傳遞的函式:LRESULT OnMsg(WPARAM wp, LPARAM lp);
在原始檔中如下新增:
void CFrameMatchWindowDlg::OnBnClickedBtnProgress()
{
_beginthread(&MyThread::Run, 0, this->GetSafeHwnd());
}
LRESULT CFrameMatchWindowDlg::OnMsg(WPARAM wp, LPARAM lp)
{
CProgressCtrl *prog = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS);
prog->SetPos((int)wp);
return 1L;
}
在BEGIN_MESSAGE_MAP裡新增:ON_MESSAGE(WM_USER_MSG, &CFrameMatchWindowDlg::OnMsg)
OnInitDialog()裡新增:
CDialogEx::OnInitDialog();
CProgressCtrl *prog = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS);
prog->SetRange(0, 100);
DoDataExchange裡新增:
DDX_Control(pDX, IDC_PROGRESS, m_proGress);
但是並不好用= =換一種思路。
先把icp匹配的過程放到多執行緒裡,避免程式卡住。
把icpdlg的OnBnClickedOk方法裡的點雲校準部分移動到一個靜態函式裡,並做適當修改:
//ICP校準
UINT CIcpDlg::IcpMatch(LPVOID lpParam)
{
CIcpDlg *pIcp = CIcpDlg::gIcpDlg;
int nTargetPoint = 0;
int nSourcePoint = 0;
//查詢點雲檔案內點的數量
CFrameMatchWindowDlg *pFMWDlg = CFrameMatchWindowDlg::gFrameMatchWindowDlg;
char* strTargetFile = new char[80];
FILE* pfTargetData;
strcpy(strTargetFile, pFMWDlg->m_strTargetCloudFile);
fopen_s(&pfTargetData, strTargetFile, "r");
if (pfTargetData == NULL)
return 0;
while (!feof(pfTargetData))
if (fgetc(pfTargetData) == '\n')
nTargetPoint++;
nTargetPoint++;//加上最後一行
cout << "target cloud contains " << nTargetPoint << " points." << endl;
fclose(pfTargetData);
char* strSourceFile = new char[80];
FILE* pfSourceData;
strcpy(strSourceFile, pFMWDlg->m_strSourceCloudFile);
fopen_s(&pfSourceData, strSourceFile, "r");
if (pfSourceData == NULL)
return 0;
while (!feof(pfSourceData))
if (fgetc(pfSourceData) == '\n')
nSourcePoint++;
nSourcePoint++;
cout << "source cloud contains " << nSourcePoint << " points." << endl;
fclose(pfSourceData);
//建立pcl點雲
PointCloud<PointXYZ>::Ptr cloud_target(new PointCloud<PointXYZ>(nTargetPoint, 1));
PointCloud<PointXYZ>::Ptr cloud_source(new PointCloud<PointXYZ>(nSourcePoint, 1));
// Fill in the cloud data
{
FILE* pfSourceData;
fopen_s(&pfSourceData, strSourceFile, "r");
if (pfSourceData == NULL) return 0;
uint64_t nTimestamp = 0;
for (auto& point : *cloud_source)
fscanf(pfSourceData, "%f,%f,%f,%f,%lld,", &point.x, &point.y, &point.z, &point.data[3], &nTimestamp);
fclose(pfSourceData);
delete[] strSourceFile;
strSourceFile = NULL;
}
{
FILE* pfTargetData;
fopen_s(&pfTargetData, strTargetFile, "r");
if (pfTargetData == NULL) return 0;
uint64_t nTimestamp = 0;
for (auto& point : *cloud_target)
fscanf(pfTargetData, "%f,%f,%f,%f,%lld,", &point.x, &point.y, &point.z, &point.data[3], &nTimestamp);
fclose(pfTargetData);
delete[] strTargetFile;
strTargetFile = NULL;
}
IterativeClosestPoint<PointXYZ, PointXYZ> icp;
icp.setInputSource(cloud_source);
icp.setInputTarget(cloud_target);
PointCloud<PointXYZ> Final;
Eigen::Matrix4f Guess;
Guess(0) = 1.0; Guess(4) = 0.0; Guess(8) = 0.0; Guess(12) = 0.0;
Guess(1) = 0.0; Guess(5) = 1.0; Guess(9) = 0.0; Guess(13) = 0.0;
Guess(2) = 0.0; Guess(6) = 0.0; Guess(10) = 1.0; Guess(14) = 0.0;
Guess(3) = 0.0; Guess(7) = 0.0; Guess(11) = 0.0; Guess(15) = 1.0;
icp.align(Final, Guess);//將source進行配準後的點雲Final
cout << "has converged:" << icp.hasConverged() << " score: " << icp.getFitnessScore() << endl;
cout << icp.getFinalTransformation() << endl;
//輸出點雲檔案
FILE* pfIcpMatchedCloud;
USES_CONVERSION;
char* strMatchedFileName = new char[80];
strcpy(strMatchedFileName, T2A(pIcp->m_strIcpMatchFilePath));
fopen_s(&pfIcpMatchedCloud, strMatchedFileName, "w");
if (pfIcpMatchedCloud == NULL) return 0;
for (int i = 0; i < Final.size(); i++)
fprintf(pfIcpMatchedCloud, "%f,%f,%f,%.1f,\n", Final.at(i).x, Final.at(i).y, Final.at(i).z, Final.at(i).data[3]);
FILE* pfIcpTargetFile;
fopen_s(&pfIcpTargetFile, pFMWDlg->m_strTargetCloudFile, "r");
if (pfIcpTargetFile == NULL) return 0;
float nReflection;
uint64_t lTimestamp;
float dTargetPointX, dTargetPointY, dTargetPointZ;
while (fscanf_s(pfIcpTargetFile, "%f,%f,%f,%f,%lld,", &dTargetPointX, &dTargetPointY, &dTargetPointZ, &nReflection, &lTimestamp) != EOF)
fprintf(pfIcpMatchedCloud, "%f,%f,%f,%.1f,\n", dTargetPointX, dTargetPointY, dTargetPointZ, nReflection);
fclose(pfIcpTargetFile);
fclose(pfIcpMatchedCloud);
delete[] strMatchedFileName;
strMatchedFileName = NULL;
//icp點對座標輸出到grid control內
pIcp->IcpCorrsToGrid();
AfxMessageBox(_T("點雲匹配完成"), NULL, NULL);
//pIcp->OnClose();
return 0;
}
主要修改的地方就是把直接引用類內成員的地方改成間接引用。
btnclickok方法裡寫:
m_winIcpMatch = AfxBeginThread(IcpMatch, NULL, THREAD_PRIORITY_NORMAL, 0, 0, NULL);
icpdlg的標頭檔案新增:
CWinThread* m_winIcpMatch = NULL;//ICP校準多執行緒
static UINT IcpMatch(LPVOID lpParam);//ICP校準多執行緒
這樣可以實現程式不卡死。
然後考慮把進度條鑲嵌在icp的對話方塊上。
對話方塊新增一個進度條控制元件,id設為IDC_ICP_PROGRESS。IcpDlg的標頭檔案裡宣告變數CProgressCtrl m_IcpProgress;
在IcpDlg的原始檔裡的DoDataExchange裡把變數關聯到控制元件DDX_Control(pDX, IDC_ICP_PROGRESS, m_IcpProgress);
。
在CIcpDlg::CIcpDlg(CWnd* pParent /*=NULL*/)
裡新增進度條的初始化:
m_IcpProgress.SetRange(0, 100);
m_IcpProgress.SetStep(1);
m_IcpProgress.SetPos(0);
接下來需要讓進度條獲取程式執行進度。因為icp配準的絕大部分耗時是在迭代部分,所以根據當前迭代次數更新進度條的顯示。
在icp.hpp裡的computeTransformation()函式裡進行修改,迭代就發生在這個函式裡的do-while迴圈。
在do-while迴圈前面計算進度條的步長,float fStep = 100.0 / pDlg->m_nMaxIter;
m_nMaxIter是在對話方塊輸入的最大迭代次數。初始進度int nProgress = 0;
。
do-while迴圈裡新增:
nProgress += fStep;
pDlg->m_IcpProgress.SetPos(nProgress);
為了防止迭代次數沒有達到設定的最大次數就結束迭代,在迴圈體的後面加上pDlg->m_IcpProgress.SetPos(100);
讓進度條直接跳到100%。
這樣的進度條就可以使用了。一開始的思路就有問題,想要把進度條放到單獨的對話方塊裡顯示,再把對話方塊的實現放到多執行緒裡。這樣就會比較繁瑣,用了一上午也沒做出來,而且這種辦法並沒有解決演算法執行過程中會讓介面卡住的問題。所以還是要從演算法多執行緒著手。
相關文章
- Android花樣loading進度條(三)-配文字環形進度條Android
- 【新特性速遞】進度條,進度條,進度條
- Qt 進度條QT
- 簡單進度條
- 學習進度條
- Python進度條技巧Python
- canvas 畫進度條Canvas
- HTML <progress> 進度條HTML
- wkwebView 新增 進度條WebView
- Linux 進度條(非100%)列出unzip進度Linux
- ProgressBar進度條顏色
- Excel實現完成進度的進度條結果Excel
- LVGL高效顯示進度條
- Python之程式碼進度條Python
- golang 進度條功能實現Golang
- psplash進度條旋轉成功
- Flutter 波浪圓形進度條Flutter
- canvas環形進度條效果Canvas
- 數字進度條元件NumberProgressBar元件
- 橡皮筋進度條ElasticProgressBarAST
- carousel 輪播自定義進度條
- 58python 進度條設計Python
- 關於WPF進度條的使用
- canvas錐形漸變進度條Canvas
- laravel自定義命令列印進度條Laravel命令列
- bat檔案進度條程式碼BAT
- c# 控制檯console進度條C#
- Python 輸出命令列進度條Python命令列
- Ajax 處理時進度條使用
- jQuery實進度條效果詳解jQuery
- Android自定義圓形進度條Android
- ios自定義圓環進度條iOS
- 短視訊商城系統,Android進度條,自定義進度條,顯示百分比Android
- 直播平臺軟體開發,讓原本沒有進度條的頁面顯示進度條
- 製作遊戲載入進度條遊戲
- Qml 實現水波進度動畫條動畫
- 讀取檔案大小-列印進度條
- 實現環形進度條效果【一】