剛開始學習Halcon,需要使用Halcon與C++聯合開發軟件,查了網上的資料都是Halcon10的,我用的是Halcon11和VS2010的開發環境,實踐了一下發現有一些問題,於是把自己的配置的過程寫出來共享一下。
首先新建一個Halcon工程,這里用個讀入圖片的簡單例子。
新建一個Halcon 程序,輸入以下代碼:
read_image (Image, 'C:/Users/lenovo/Desktop/test.jpg') dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_clear_window () dev_display (Image)
其實就是打開一個窗口並顯示桌面上的一幅畫
然后將Halcon程序導出為C++程序
在halcon中點擊菜單欄的文件->導出。
導出之后就能在桌面上看到一個Halcon.cpp文件,這個文件的內容如下:
先聲明並給出了函數dev_open_window_fit_image
的定義:
void dev_open_window_fit_image (HObject ho_Image, HTuple hv_Row, HTuple hv_Column,
HTuple hv_WidthLimit, HTuple hv_HeightLimit, HTuple *hv_WindowHandle);
然后是函數Action的定義,Action里的代碼對應着剛才Halcon中的代碼,簡單地說,就是把Halcon語言翻譯成C++了。
// Main procedure
void action()
{
// Local iconic variables
HObject ho_Image;
// Local control variables
HTuple hv_WindowHandle;
ReadImage(&ho_Image, "C:/Users/lenovo/Desktop/test.jpg");
dev_open_window_fit_image(ho_Image, 0, 0, -1, -1, &hv_WindowHandle);
if (HDevWindowStack::IsOpen())
ClearWindow(HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, HDevWindowStack::GetActive());
}
配置VS2010
為了一勞永逸的配置好VS2010,讓我們在以后每次新建工程的時候都不用重新添加這些亂七八糟的配置項,需要采用以下的技巧。首先新建一個基於對話框的MFC程序,然后點擊菜單欄的視圖->屬性管理器,在左側的屬性管理器中,默認會有32位的Debug和Release屬性。對64位的系統(現在電腦一般都是64位系統),需要點擊菜單欄的生成->配置管理器,把平台選項改為x64,這樣生成的文件就可以在64位系統下運行了。
改完之后,屬性管理器還不會立馬變化,關閉項目再重新開啟就能看到新增的x64屬性了。
下面以64位的Debug屬性為例,介紹一下halcon 11的配置。
在User屬性上點擊右鍵,選擇屬性,進入屬性頁面。
向通用屬性下的VC++目錄中的包含目錄中添加如下目錄,據說halcon11需要包含halconcpp這個文件夾就夠了,halcon10則是cpp。我用的是halcon11,打開安裝目錄之后發現兩個文件夾都有,於是就把倆目錄都添加進去了。
下一步是VC++目錄中的庫目錄。
目錄中的環境變量HALCONROOT是安裝Halcon時自動寫入到系統環境變量中的。
繼續,在C/C++目錄中,為附加包含目錄添加下面兩項(當然也可以添加$(HALCONROOT)\include\cpp這一項,並無影響)
最有一項,配置鏈接器。在常規項的附加庫目錄中添加$(HALCONROOT)\lib\$(HALCONARCH),同樣,HALCONARCH是環境變量。
為輸入的附加依賴項添加halconcpp.lib。
至此,配置完畢。
注意,采用這種方式配置,以后新建的工程都會繼承這些配置,無需重新配置,非常方便。
MFC程序
點擊菜單欄中的視圖->資源視圖,並在資源視圖中打開對話框。
為了實現顯示圖片的功能,在對話框中添加一個按鈕,並雙擊按鈕進入事件響應函數,空空如也,待我們填寫。
void CHalconVCDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知處理程序代碼
}
首先在HalconVCDlg.h中添加頭文件及命名空間,因為等會要在這個頭文件里添加halcon函數的聲明。然后在HalconVCDlg.cpp中也添加上述頭文件及命名空間,因為要在這里調用halcon的函數。
#include "halconcpp.h"
using namespace HalconCpp;
打開剛剛導出的Halcon.cpp,為了能夠在MFC中調用dev_open_window_fit_image 這個函數,需要把它的聲明和定義都放進MFC程序中。聲明拷貝到HalconVCDlg.h中,注意要放在對話框類聲明外面,定義拷貝到HalconVCDlg.cpp中。
下面進行最重要的一部,把Action中的代碼拷貝到OnBnClickedButton1() 中,這樣點擊按鈕就會執行在halcon中實現的顯示圖片功能了。
Action函數中定義了兩個變量
HObject ho_Image;
HTuple hv_WindowHandle;
為了在Button1的響應函數中使用這兩個變量,之前博文中的作法是將其定義為HalconVCDlg.h中對話框類的成員變量,事實上,直接定義在void CHalconVCDlg::OnBnClickedButton1() 函數中或者是HalconVCDlg.cpp文件中也是沒有問題的,但是定義在HalconVCDlg.h中作為HalconVCDlg的類外變量卻不行。
了解到這一點,我們就可以直接把Action函數中所有東西一起拷貝進OnBnClickedButton1()了。
// Local iconic variables
HObject ho_Image;
// Local control variables
HTuple hv_WindowHandle;
ReadImage(&ho_Image, "C:/Users/lenovo/Desktop/test.jpg");
dev_open_window_fit_image(ho_Image, 0, 0, -1, -1, &hv_WindowHandle);
if (HDevWindowStack::IsOpen())
ClearWindow(HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, HDevWindowStack::GetActive());
運行結果
每點擊一次Button1就會彈出一個窗口顯示我們的圖片(沒錯,這是一張我桌面的截圖)
全部程序代碼
MFC程序中HalconVCDlg.h
// HalconVCDlg.h : 頭文件
#pragma once
//與halcon有關的頭文件
#include "halconcpp.h"
using namespace HalconCpp;
// CHalconVCDlg 對話框
class CHalconVCDlg : public CDialogEx
{
// 構造
public:
CHalconVCDlg(CWnd* pParent = NULL); // 標准構造函數
//Halcon中用到的變量,為何要定義為類中的變量
//HObject ho_Image;
//HTuple hv_WindowHandle;
// 對話框數據
enum { IDD = IDD_HALCONVC_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 實現
protected:
HICON m_hIcon;
// 生成的消息映射函數
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
};
void dev_open_window_fit_image (HObject ho_Image, HTuple hv_Row, HTuple hv_Column,
HTuple hv_WidthLimit, HTuple hv_HeightLimit, HTuple *hv_WindowHandle);
MFC程序中HalconVCDlg.cpp
// HalconVCDlg.cpp : 實現文件 #include "stdafx.h" #include "HalconVC.h" #include "HalconVCDlg.h" #include "afxdialogex.h" //與halcon有關的頭文件 #include "halconcpp.h" #ifdef _DEBUG #define new DEBUG_NEW #endif using namespace HalconCpp;
中間省略一堆系統生成的函數,下面是我們主要的改動
// Procedures
// Chapter: Develop
// Short Description: Open a new graphics window that preserves the aspect ratio of the given image.
void dev_open_window_fit_image (HObject ho_Image, HTuple hv_Row, HTuple hv_Column,
HTuple hv_WidthLimit, HTuple hv_HeightLimit, HTuple *hv_WindowHandle)
{
// Local control variables
HTuple hv_MinWidth, hv_MaxWidth, hv_MinHeight;
HTuple hv_MaxHeight, hv_ResizeFactor, hv_ImageWidth, hv_ImageHeight;
HTuple hv_TempWidth, hv_TempHeight, hv_WindowWidth, hv_WindowHeight;
//This procedure opens a new graphics window and adjusts the size
//such that it fits into the limits specified by WidthLimit
//and HeightLimit, but also maintains the correct image aspect ratio.
//
//If it is impossible to match the minimum and maximum extent requirements
//at the same time (f.e. if the image is very long but narrow),
//the maximum value gets a higher priority,
//
//Parse input tuple WidthLimit
if (0 != (HTuple((hv_WidthLimit.TupleLength())==0).TupleOr(hv_WidthLimit<0)))
{
hv_MinWidth = 500;
hv_MaxWidth = 800;
}
else if (0 != ((hv_WidthLimit.TupleLength())==1))
{
hv_MinWidth = 0;
hv_MaxWidth = hv_WidthLimit;
}
else
{
hv_MinWidth = ((const HTuple&)hv_WidthLimit)[0];
hv_MaxWidth = ((const HTuple&)hv_WidthLimit)[1];
}
//Parse input tuple HeightLimit
if (0 != (HTuple((hv_HeightLimit.TupleLength())==0).TupleOr(hv_HeightLimit<0)))
{
hv_MinHeight = 400;
hv_MaxHeight = 600;
}
else if (0 != ((hv_HeightLimit.TupleLength())==1))
{
hv_MinHeight = 0;
hv_MaxHeight = hv_HeightLimit;
}
else
{
hv_MinHeight = ((const HTuple&)hv_HeightLimit)[0];
hv_MaxHeight = ((const HTuple&)hv_HeightLimit)[1];
}
//
//Test, if window size has to be changed.
hv_ResizeFactor = 1;
GetImageSize(ho_Image, &hv_ImageWidth, &hv_ImageHeight);
//First, expand window to the minimum extents (if necessary).
if (0 != (HTuple(hv_MinWidth>hv_ImageWidth).TupleOr(hv_MinHeight>hv_ImageHeight)))
{
hv_ResizeFactor = (((hv_MinWidth.TupleReal())/hv_ImageWidth).TupleConcat((hv_MinHeight.TupleReal())/hv_ImageHeight)).TupleMax();
}
hv_TempWidth = hv_ImageWidth*hv_ResizeFactor;
hv_TempHeight = hv_ImageHeight*hv_ResizeFactor;
//Then, shrink window to maximum extents (if necessary).
if (0 != (HTuple(hv_MaxWidth<hv_TempWidth).TupleOr(hv_MaxHeight<hv_TempHeight)))
{
hv_ResizeFactor = hv_ResizeFactor*((((hv_MaxWidth.TupleReal())/hv_TempWidth).TupleConcat((hv_MaxHeight.TupleReal())/hv_TempHeight)).TupleMin());
}
hv_WindowWidth = hv_ImageWidth*hv_ResizeFactor;
hv_WindowHeight = hv_ImageHeight*hv_ResizeFactor;
//Resize window
SetWindowAttr("background_color","black");
OpenWindow(hv_Row,hv_Column,hv_WindowWidth,hv_WindowHeight,0,"","",&(*hv_WindowHandle));
HDevWindowStack::Push((*hv_WindowHandle));
if (HDevWindowStack::IsOpen())
SetPart(HDevWindowStack::GetActive(),0, 0, hv_ImageHeight-1, hv_ImageWidth-1);
return;
}
void CHalconVCDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知處理程序代碼
HObject ho_Image;
HTuple hv_WindowHandle;
ReadImage(&ho_Image, "C:/Users/lenovo/Desktop/test.jpg");
dev_open_window_fit_image(ho_Image, 0, 0, -1, -1, &hv_WindowHandle);
//open_window(0,0,600,600,0,"","",&hv_WindowHandle);
if (HDevWindowStack::IsOpen())
ClearWindow(HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, HDevWindowStack::GetActive());
}










