<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python+OpenCV與海康工業(yè)相機(jī)交互

          共 4053字,需瀏覽 9分鐘

           ·

          2023-03-08 07:43

          點(diǎn)擊下方卡片,關(guān)注“新機(jī)器視覺”公眾號(hào)

          重磅干貨,第一時(shí)間送達(dá)

            來源 | 點(diǎn)云PCL

          1前言

          因?yàn)轫?xiàng)目的原因,筆者需要開發(fā)自己的程序與海康工業(yè)相機(jī)(黑白相機(jī))進(jìn)行實(shí)時(shí)交互,而不是簡單的使用海康的驅(qū)動(dòng)來調(diào)用相機(jī)。

          在經(jīng)歷了反復(fù)的踩坑填坑之后,筆者總結(jié)了利用c#和python與海康相機(jī)交互的方法。


          2

          準(zhǔn)備工作

          無論是用c#還是python,都要通過海康的SDK來進(jìn)行二次開發(fā)。海康的SDK實(shí)際上就是一個(gè)第三方庫文件,里面有各種用于海康相機(jī)交互的函數(shù),這些函數(shù)被封裝成供各大編程語言使用的dll或者lib文件。你可以像使用OpenCV樣調(diào)用海康的SDK。


          海康提供了各個(gè)編程語言的例程,可以讓我們對(duì)照例程快速上手。海康的例程一般放在相機(jī)驅(qū)動(dòng)軟件的安裝文件夾下,具體路徑為 …\MVS\Development\Samples

          里面有大部分主流語言的例程:

          除此之外,海康還提供了SDK的說明文檔,文件路徑在

          …\MVS\Development\Documentations

          c#可以參考.net版本的,python和c可以參考c版本的(兩者差別都不大)。

          3

          C#調(diào)用

          在c#中的例程里面,有很多程序

          但除了basicdemo有界面,其他的都是控制臺(tái)程序,顯示不了圖片。而且basicdemo基本涵蓋了海康相機(jī)使用的各個(gè)方面,所以推薦優(yōu)先學(xué)習(xí)basicdemo程序。

          該程序的主界面如下圖所示:

          需要注意的是,雖然這里能顯示圖片,但得到的圖片數(shù)據(jù)仍然是海康的圖片格式,不是opencv可以處理的mat格式。筆者嘗試了很多次,鑒于對(duì)C#不是很熟練,暫時(shí)無法將其轉(zhuǎn)為可供opencv處理的數(shù)據(jù)格式。這一功能我在python中實(shí)現(xiàn)了。

          4

          Python調(diào)用

          python的話,參考例程中的grabimg程序,對(duì)里面的線程進(jìn)行改造即可。但這里也有一些問題需要注意

          首先,官網(wǎng)給的源程序只能在控制臺(tái)顯示得到的圖片幀的長和寬,并沒有取得圖片的數(shù)據(jù)。但這明顯不是我們想要的。所以需要對(duì)其進(jìn)行改造,改造的部分主要在線程函數(shù)中

          def work_thread(cam=0, pData=0, nDataSize=0):stOutFrame = MV_FRAME_OUT()memset(byref(stOutFrame), 0, sizeof(stOutFrame))while True:ret = cam.MV_CC_GetImageBuffer(stOutFrame, 1000)if None != stOutFrame.pBufAddr and 0 == ret:print ("get one frame: Width[%d], Height[%d], nFrameNum[%d]"  % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))nRet = cam.MV_CC_FreeImageBuffer(stOutFrame)else:print ("no data[0x%x]" % ret)if g_bExit == True:break


          這是官方的線程函數(shù)。我們需要在里面進(jìn)行改造。

          改造之后的函數(shù)為

          def work_thread2(cam=0, pData=0, nDataSize=0):# 輸出幀的信息stFrameInfo = MV_FRAME_OUT_INFO_EX()# void *memset(void *s, int ch, size_t n);# 函數(shù)解釋:將s中當(dāng)前位置后面的n個(gè)字節(jié) (typedef unsigned int size_t )用 ch 替換并返回 s# memset:作用是在一段內(nèi)存塊中填充某個(gè)給定的值,它是對(duì)較大的結(jié)構(gòu)體或數(shù)組進(jìn)行清零操作的一種最快方法# byref(n)返回的相當(dāng)于C的指針右值&n,本身沒有被分配空間# 此處相當(dāng)于將幀信息全部清空了memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))

          while True:temp = np.asarray(pData) # 將c_ubyte_Array轉(zhuǎn)化成ndarray得到(3686400,)# print(temp)# print(temp.shape)temp = temp.reshape((2048, 1024, 3)) # 根據(jù)自己分辨率進(jìn)行轉(zhuǎn)化# temp = cv2.cvtColor(temp, cv2.COLOR_BGR2RGB) # 這一步獲取到的顏色不對(duì),因?yàn)槟J(rèn)是BRG,要轉(zhuǎn)化成RGB,顏色才正常gray = cv2.cvtColor(temp,cv2.COLOR_BGR2GRAY)ret,binary = cv2.threshold(gray,130,255,cv2.THRESH_BINARY)cv2.namedWindow("binary", cv2.WINDOW_NORMAL)cv2.namedWindow("ori", cv2.WINDOW_NORMAL)cv2.imshow('binary',binary)cv2.imshow("ori", temp)if cv2.waitKey(1) & 0xFF == ord('q'):break# 采用超時(shí)機(jī)制獲取一幀圖片,SDK內(nèi)部等待直到有數(shù)據(jù)時(shí)返回,成功返回0ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)if ret == 0:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nFrameNum))else:print("no data[0x%x]" % ret)if g_bExit == True:breakcv2.waitKey()


          除此之外,還有幾個(gè)點(diǎn)需要注意

          第一個(gè)

          sys.path.append(r"**\MvImport")

          因?yàn)樾枰玫絊DK的接口函數(shù),所以需要導(dǎo)入相應(yīng)的庫,官方的路徑是這樣的,這是因?yàn)檫@個(gè)包在程序的同一個(gè)文件夾下,所以前面的都可以省略,但我們使用的時(shí)候,最好把它的絕對(duì)路徑給寫上,我的路徑是這樣的,可以參考

          sys.path.append(r"C:\Users\Administrator\Desktop\python_vscode\MvImport")


          第二個(gè)

          在線程函數(shù)之外,還有幾個(gè)關(guān)鍵語句需要注意



          #ch:獲取數(shù)據(jù)包大小 | en:Get payload sizestParam = MVCC_INTVALUE()#csharp中沒有memset函數(shù),用什么代替?memset(byref(stParam), 0, sizeof(MVCC_INTVALUE))# MV_CC_GetIntValue,獲取Integer屬性值,handle [IN] 設(shè)備句柄 # strKey [IN] 屬性鍵值,如獲取寬度信息則為"Width" # pIntValue [IN][OUT] 返回給調(diào)用者有關(guān)相機(jī)屬性結(jié)構(gòu)體指針# 得到圖片尺寸,這一句很關(guān)鍵# payloadsize,為流通道上的每個(gè)圖像傳輸?shù)淖畲笞止?jié)數(shù),相機(jī)的PayloadSize的典型值是(寬x高x像素大小),此時(shí)圖像沒有附加任何額外信息ret = cam.MV_CC_GetIntValue("PayloadSize", stParam)


          cam.MV_CC_GetIntValue(“PayloadSize”, stParam)這一句中的PayloadSize是流通道上的每個(gè)圖像傳輸?shù)淖畲笞止?jié)數(shù),相機(jī)的PayloadSize的典型值是(寬x高x像素大小),這是一個(gè)很關(guān)鍵的步驟,官方例子中并沒有獲得這個(gè)值。

          nPayloadSize = stParam.nCurValue     # ch:開始取流 | en:Start grab image    ret = cam.MV_CC_StartGrabbing()    if ret != 0:        print ("start grabbing fail! ret[0x%x]" % ret)        sys.exit()    #  關(guān)鍵句,官方?jīng)]有這個(gè)句子,抓取的圖片數(shù)據(jù)是空的,CSharp中怎么實(shí)現(xiàn)這句話。    data_buf = (c_ubyte * nPayloadSize)()


          data_buf = (c_ubyte * nPayloadSize)()這一句話將PayloadSize的uint數(shù)據(jù)轉(zhuǎn)為可供numpy處理的數(shù)據(jù),后面就可以用numpy將其轉(zhuǎn)化為numpy數(shù)組格式。



          第三個(gè),線程的使用

          官方例子是

          hThreadHandle = threading.Thread(target=work_thread, args=(cam, None,None))hThreadHandle.start()

          此處需要改成

          try:hThreadHandle = threading.Thread(target=work_thread2, args=(cam, data_buf, nPayloadSize))hThreadHandle.start()

          在這里,有些代碼可能會(huì)在data_buf前面加上byteref,如果這樣做的話,就會(huì)將數(shù)據(jù)轉(zhuǎn)為浮點(diǎn)型,而opencv需要的是整型,會(huì)報(bào)錯(cuò),所以這里就不需要轉(zhuǎn)化了。


          本文僅做學(xué)術(shù)分享,如有侵權(quán),請(qǐng)聯(lián)系刪文。

          —THE END—

          瀏覽 426
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月丁香婷婷社区 | 久久永久免费视频 | 翔田千里无码一区二区 | 国产成人自拍网 | 在线欧美网址 |