剛開始學習Halcon,需要使用Halcon與C++聯合開發軟體,查了網上的資料都是Halcon10的,我用的是Halcon11和VS2010的開發環境,實踐了一下發現有一些問題,於是把自己的配置的過程寫出來共用一下。 首先新建一個Halcon工程,這裡用個讀入圖片的簡單例子。 新建一個Halcon... ...
剛開始學習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()); }