完整解決方案:Halcon+VisualStudio2015使用線(xiàn)程實(shí)現大恒水星相機實(shí)時(shí)圖像采
優(yōu)采云 發(fā)布時(shí)間: 2022-10-24 07:51完整解決方案:Halcon+VisualStudio2015使用線(xiàn)程實(shí)現大恒水星相機實(shí)時(shí)圖像采
實(shí)時(shí)采集圖像,您可以將采集圖像保存到本地文件夾
具體的C#代碼如下:
使用系統;
使用系統.集合.通用;
使用系統組件模型;
使用系統數據;
使用系統繪圖;
使用系統;
使用系統文本;
使用系統線(xiàn)程;
使用系統.Windows.Forms;
使用光標網(wǎng);
使用 System.IO;
命名空間演示
{
公共分部類(lèi)圖像采集:形式
{
私有線(xiàn)程線(xiàn)程對象;線(xiàn)程
私有布爾線(xiàn)程停止 = 假; // 確定線(xiàn)程是否已關(guān)閉
私有 HTuple 窗口 ID;
公眾形象采集().
{
初始化組件();
線(xiàn)程對象實(shí)例化
線(xiàn)程對象 = 新線(xiàn)程(新線(xiàn)程啟動(dòng)(線(xiàn)程函數));
創(chuàng )建哈爾康窗口();// 創(chuàng )建哈爾康顯示窗口
}
公共空白創(chuàng )建哈爾康窗口()
{
HTUPLE父親窗口 = 這個(gè)。DisplayVideo_pictureBox.手柄;
設置窗口的背景色
HOperatorSet.SetWindowAttr(“background_color”,“黑色”);
HOperatorSet.OpenWindow(0, 0, this.DisplayVideo_pictureBox.寬度,這個(gè)。DisplayVideo_pictureBox.身高,父親窗口,“可見(jiàn)”,“”,窗外ID);
}
線(xiàn)程回調函數
公共空隙線(xiàn)程函數()
{
對象 ho_Image = 空;
hv_AcqHandle = 空;
HOperatorSet.GenEmptyObj(out ho_Image);
HOperatorSet.OpenFramegrabber(“GenICamTL”, 0, 0, 0, 0, 0, 0, “默認”, -1, “默認”, -1, “false” , “default” “MER-131-210U3M(KG0170060082)”, 0, -1, 出hv_AcqHandle);
300萬(wàn)像素:1280*1024
整數圖像寬度 = 1280;
整型圖像高度 = 1024;//
線(xiàn)程停止 = 假;
而 (!線(xiàn)程停止)
{
//ho_Image.dispose();
//HOperatorSet.GrabImage(出ho_Image,hv_AcqHandle);
HOperatorSet.GrabImageStart(hv_AcqHandle, -1);
ho_Image.處置();
HOperatorSet.GrabImageAsync(出ho_Image, hv_AcqHandle, -1);
調整圖像
通過(guò)更改圖像的比例來(lái)正常顯示窗口
HOperatorSet.SetPart(WindowID, 0, 0, ImageHeight, ImageWidth);
在窗口中顯示圖像
HOperatorSet.dispObj(ho_Image, WindowID);
如果(這個(gè)。SaveImage_checkBox.已選中)
{
字符串文件名 = DateTime.Now.ToString(“yyyyy-year mm 月 dd 日 HH 小時(shí) mm分鐘秒 fff 毫秒”);
HOperatorSet.WriteImage(ho_Image, “bmp”, 0, Directory.GetCurrentDirectory() + “/image/” + 文件名 + “.bmp”);
}
}
HOperatorSet.CloseFramegrabber(hv_AcqHandle);
ho_Image.處置();
}
私有 void DisplayImage_button_Click(對象發(fā)送方,事件Args e)
{
if (線(xiàn)程對象.線(xiàn)程狀態(tài) == 系統.線(xiàn)程連接.線(xiàn)程狀態(tài).未啟動(dòng))
{
線(xiàn)程對象啟動(dòng)();
}
如果 ((線(xiàn)程對象.線(xiàn)程狀態(tài) == 系統.線(xiàn)程.線(xiàn)程狀態(tài).已停止) ||(線(xiàn)程對象.線(xiàn)程狀態(tài) == 系統.線(xiàn)程連接.線(xiàn)程狀態(tài).中止))
{
線(xiàn)程對象 = 新線(xiàn)程(新線(xiàn)程啟動(dòng)(線(xiàn)程函數));
線(xiàn)程對象啟動(dòng)();
}
}
私有 void StopPlay_button_Click(對象發(fā)送方,事件Args e)
{
線(xiàn)程停止 = 真;
}
}
}
控制用戶(hù)界面界面:
直觀(guān):并發(fā)隊列:ArrayBlockingQueue實(shí)際運用場(chǎng)景和原理
陣列塊隊列實(shí)際應用場(chǎng)景
之前,我在一家公司做過(guò)一個(gè)情感識別系統,通過(guò)調用*敏*感*詞*接口采集人臉信息,對采集人臉信息進(jìn)行人臉識別和情感分析,最后通過(guò)一定的算法將個(gè)人情感數據轉換為特定的行為指標值。圖片采集部分使用并發(fā)隊列數組阻止隊列。
如上圖所示:有n臺攝像機,單線(xiàn)程采集的效率會(huì )比較慢,所以在采集攝像機的過(guò)程中是多線(xiàn)程的,圖片采集需要存儲在圖片服務(wù)器中,對圖片服務(wù)器寫(xiě)入的要求也很高,圖片服務(wù)器是集群化的,還需要多線(xiàn)程化。圖片存儲完畢后,圖片數據需要發(fā)送到人臉?lè )治龇?wù)器進(jìn)行處理,這涉及到分布式消息,因此黑點(diǎn)部分使用kafka傳遞消息。多線(xiàn)程圖片的紅色虛線(xiàn)部分采集信息傳遞到 ArrayBlockingQueue 中使用的多線(xiàn)程圖片存儲,該存儲是并發(fā)安全隊列。
數組阻塞隊列簡(jiǎn)化了類(lèi)圖結構
從類(lèi)圖中可以看出,Queue 接口提供了用于添加、提供到隊列中以及提供用于輪詢(xún)隊列的方法的方法!
阻塞隊列接口添加了一個(gè)放入隊列的方法,并提供了一種取出隊列的方法!
附加說(shuō)明:UML 類(lèi)圖結構:
并發(fā)隊列阻塞和非阻塞概念
從上面的類(lèi)圖名稱(chēng)中,可以看出 Queue 提供的方法不是阻塞的!把,拿的方法,封鎖隊列提供的辦法是封鎖!讓我們遵循舊的想法,讓我們用代碼來(lái)解釋阻塞和非阻塞!
非阻塞
import?java.util.concurrent.ArrayBlockingQueue;
/**
?*?@author?:jiaolian
?*?@date?:Created?in?2021-02-02?20:16
?*?@description:ArrayBlockingQueue阻塞非阻塞測試
?*?@modified?By:
?*?公眾號:叫練
?*/
public?class?ArrayBlockingQueueTest?{
<p>
????public?static?void?main(String[]?args)?{
????????ArrayBlockingQueue?arrayBlockingQueue?=?new?ArrayBlockingQueue(1);
????????arrayBlockingQueue.offer("叫練");
????????arrayBlockingQueue.offer("叫練");
????????//輸出arrayBlockingQueue的長(cháng)度
????????System.out.println(arrayBlockingQueue.size());
????}
}</p>
如上面的代碼所示:將數組塊隊列的長(cháng)度設置為1,通過(guò)提供方法向隊列中添加2個(gè)元素,最后打印數組塊隊列的長(cháng)度?答案是1,它不會(huì )阻塞,因為offer方法丟棄了第二個(gè)元素“喊叫”,我們說(shuō)允許隊列繼續執行并加入我們調用的隊列非阻塞。如果切換到 add 方法,該怎么辦?將報告錯誤隊列溢出,如下圖所示!但它還沒(méi)有阻止。我們來(lái)看看有哪些堵塞!
阻塞
import?java.util.concurrent.ArrayBlockingQueue;
/**
?*?@author?:jiaolian
?*?@date?:Created?in?2021-02-02?20:16
?*?@description:ArrayBlockingQueue阻塞非阻塞測試
?*?@modified?By:
?*?公眾號:叫練
?*/
public?class?ArrayBlockingQueueTest?{
????public?static?void?main(String[]?args)?throws?InterruptedException?{
????????ArrayBlockingQueue?arrayBlockingQueue?=?new?ArrayBlockingQueue(1);
<p>
????????arrayBlockingQueue.put("叫練");
????????arrayBlockingQueue.put("叫練");
????????//輸出arrayBlockingQueue的長(cháng)度
????????System.out.println(arrayBlockingQueue.size());
????}
}</p>
如上面的代碼所示:數組塊隊列長(cháng)度為1,通過(guò) put 方法向隊列中添加 2 個(gè)元素,最后輸出數組阻止隊列長(cháng)度是多少?答案是控制臺繼續運行,因為程序在添加第二個(gè)“調用”時(shí)會(huì )阻塞。我們說(shuō),不能允許的隊列繼續執行,當我們離開(kāi)隊列并加入隊列時(shí),我們調用阻塞,添加方法,輪詢(xún)方法,采取方法 我們不會(huì )一一給出例子,你可以編寫(xiě)代碼來(lái)做最簡(jiǎn)單的測試!
好吧,讓我們總結一下幾種方法!
優(yōu)惠:隊列已滿(mǎn)且已丟棄。
add:隊列已滿(mǎn),但有錯誤。
放置:塊。
輪詢(xún) :如果隊列為空,則返回 null。
采?。鹤柚?。
分析數組塊隊列的實(shí)現原理
如上所示,數組阻止隊列是用數組實(shí)現的,重入鎖獨占鎖控制數組的進(jìn)入和退出。讓我們來(lái)看看采取,放置方法流,其他方法也是如此。
完全無(wú)阻塞隊列并發(fā)鏈接隊列
ConcurrentLinkedQueue還實(shí)現了隊列接口,提供提供,添加,輪詢(xún)方法都是非阻塞的,并且從名稱(chēng)中可以看出,底層是鏈表結構,cas是旋轉用于隊列內外的。
列出多線(xiàn)程安全方案:鏈接阻止隊列
鏈接阻止隊列和數組阻止隊列是相似的,鏈接阻止隊列是
有界,長(cháng)度為整數.MAX_VALUE,實(shí)現時(shí),鏈接塊隊列是一個(gè)鏈接列表,并且是一個(gè)雙鎖,如上圖所示,采取Lock獨占鎖控制隊列頭,putLock控制隊列的末尾,不相互影響,目的是增加鏈接塊隊列的并發(fā)性。
總結