简体   繁体   English

如何使用 Python 从 GIGE 相机读取和捕获图像?

[英]How can I use Python to read and capture images from a GIGE camera?

I have been working on a codebar recognition project for weeks,.我已经在代码条识别项目上工作了数周。 I was asked to use GIGE cameras to recognize the code bars from a PCB and I choosed to use python for the job.我被要求使用 GIGE 相机识别 PCB 上的代码条,我选择使用 python 来完成这项工作。 So far, I've finished the recognition of codebars from a picture with Opencv. The problem is how to connect to a GIGE camera and grab a photo with My program.至此,我已经完成了对一张Opencv图片的codebars的识别。问题是如何连接GIGE相机,用My program抓图。 Unfortunately, I found Opencv doesn't support GIGE camera so I had to choose Halcon instead.不幸的是,我发现 Opencv 不支持 GIGE 相机,所以我不得不选择 Halcon。 However, even though I can use HDevelop to connect and capture the image, I find no solution to link it to my Python program as Halcon program can only be exported as C# or C++然而,即使我可以使用 HDevelop 连接和捕获图像,我也找不到将其链接到我的 Python 程序的解决方案,因为 Halcon 程序只能导出为 C# 或 C++

btw, I tried to use pytho.net and ironPython, but I don't how could I use them to execute a C# script(.cs file)顺便说一句,我尝试使用 pytho.net 和 ironPython,但我不知道如何使用它们来执行 C# 脚本(.cs 文件)

I was struggling a lot with this, but I found this method by accident.我为此苦苦挣扎,但我偶然发现了这种方法。 I have an IDS industrial vision camera (IDS GV-5860-CP) which has a supported Python library.我有一个 IDS 工业视觉相机 (IDS GV-5860-CP),它有一个支持的 Python 库。 The IDS Peak IPL SDK has an extension to convert the image to a NumPy 3D array. IDS Peak IPL SDK 有一个扩展,可以将图像转换为 NumPy 3D 数组。

My code makes connection with the camera and accesses the datastream of the Camera.我的代码与相机建立连接并访问相机的数据流。 This datastream fills the buffer with data that is converted to an image.此数据流用转换为图像的数据填充缓冲区。 This conversion needs to be known RGB formats.这种转换需要已知的 RGB 格式。 That data is written in an RGB format that is shaped in arrays. Those arrays can be turn in to a NumPy 3D array.该数据以 arrays 形状的 RGB 格式写入。这些 arrays 可以转换为 NumPy 3D 数组。 This array is accessible for OpenCV and can be showed as an image.该数组可供 OpenCV 访问,并可以显示为图像。

Most of the Gige Vision camera's work with buffers.大多数 Gige Vision 相机都使用缓冲区。 Be cautious because buffers can cause delay.要小心,因为缓冲区会导致延迟。 If the acquired buffer is converted to an image (NOT WRITTEN, WRITING AN IMAGE TAKES A LOT OF PROCESING POWER), the converted image only needs to be changed in a NumPy 3D array to acquire your image that can be shown in the OpenCV window.如果将获取的缓冲区转换为图像(未写入,写入图像需要大量处理能力),则转换后的图像只需要在 NumPy 3D 数组中进行更改即可获取可以在 OpenCV window 中显示的图像。

This is my code with the IDS industrial Camera, hopefully it can help by your own project.这是我用IDS工业相机的代码,希望对你自己的项目有所帮助。

My code:我的代码:

import numpy as np 
import cv2
import sys

from ids_peak import ids_peak as peak
from ids_peak_ipl import ids_peak_ipl as ipl
from ids_peak import ids_peak_ipl_extension






m_device = None
m_dataStream = None
m_node_map_remote_device = None
out = None


def open_camera():
  print("connection- camera")
  global m_device, m_node_map_remote_device
  try:
      # Create instance of the device manager
    device_manager = peak.DeviceManager.Instance()
 
      # Update the device manager
    device_manager.Update()
 
      # Return if no device was found
    if device_manager.Devices().empty():
      return False
 
      # open the first openable device in the device manager's device list
    device_count = device_manager.Devices().size()
    for i in range(device_count):
        if device_manager.Devices()[i].IsOpenable():
            m_device = device_manager.Devices()[i].OpenDevice(peak.DeviceAccessType_Control)
 
              # Get NodeMap of the RemoteDevice for all accesses to the GenICam NodeMap tree
            m_node_map_remote_device = m_device.RemoteDevice().NodeMaps()[0]
            min_frame_rate = 0
            max_frame_rate = 50
            inc_frame_rate = 0

            
            # Get frame rate range. All values in fps.
            min_frame_rate = m_node_map_remote_device.FindNode("AcquisitionFrameRate").Minimum()
            max_frame_rate = m_node_map_remote_device.FindNode("AcquisitionFrameRate").Maximum()
            
            if m_node_map_remote_device.FindNode("AcquisitionFrameRate").HasConstantIncrement():
                inc_frame_rate = m_node_map_remote_device.FindNode("AcquisitionFrameRate").Increment()
            else:
                # If there is no increment, it might be useful to choose a suitable increment for a GUI control element (e.g. a slider)
                inc_frame_rate = 0.1
            
            # Get the current frame rate
            frame_rate = m_node_map_remote_device.FindNode("AcquisitionFrameRate").Value()
            
            # Set frame rate to maximum
            m_node_map_remote_device.FindNode("AcquisitionFrameRate").SetValue(max_frame_rate)
        return True
  except Exception as e:
      # ...
    str_error = str(e)
    print("Error by connection camera")
    return False
 
 
def prepare_acquisition():
  print("opening stream")
  global m_dataStream

  try:
    data_streams = m_device.DataStreams()
    if data_streams.empty():
      print("no stream possible")
      # no data streams available
      return False
 
    m_dataStream = m_device.DataStreams()[0].OpenDataStream()
    print("open stream")
 
    return True
  except Exception as e:
      # ...
      str_error = str(e)
      print("Error by prep acquisition")
      return False
 
 
def set_roi(x, y, width, height):
  print("setting ROI")
  try:
      # Get the minimum ROI and set it. After that there are no size restrictions anymore
    x_min = m_node_map_remote_device.FindNode("OffsetX").Minimum()
    y_min = m_node_map_remote_device.FindNode("OffsetY").Minimum()
    w_min = m_node_map_remote_device.FindNode("Width").Minimum()
    h_min = m_node_map_remote_device.FindNode("Height").Minimum()
 
    m_node_map_remote_device.FindNode("OffsetX").SetValue(x_min)
    m_node_map_remote_device.FindNode("OffsetY").SetValue(y_min)
    m_node_map_remote_device.FindNode("Width").SetValue(w_min)
    m_node_map_remote_device.FindNode("Height").SetValue(h_min)
 
      # Get the maximum ROI values
    x_max = m_node_map_remote_device.FindNode("OffsetX").Maximum()
    y_max = m_node_map_remote_device.FindNode("OffsetY").Maximum()
    w_max = m_node_map_remote_device.FindNode("Width").Maximum()
    h_max = m_node_map_remote_device.FindNode("Height").Maximum()
 
    if (x < x_min) or (y < y_min) or (x > x_max) or (y > y_max):
      print("Error x and y values")
      return False
    elif (width < w_min) or (height < h_min) or ((x + width) > w_max) or ((y + height) > h_max):
      print("Error width and height")
      return False
    else:
          # Now, set final AOI
        m_node_map_remote_device.FindNode("OffsetX").SetValue(x)
        m_node_map_remote_device.FindNode("OffsetY").SetValue(y)
        m_node_map_remote_device.FindNode("Width").SetValue(width)
        m_node_map_remote_device.FindNode("Height").SetValue(height)
 
        return True
  except Exception as e:
      # ...
       str_error = str(e)
       print("Error by setting ROI")
       print(str_error)
       return False
 
 
def alloc_and_announce_buffers():
  print("allocating buffers")
  try:
    if m_dataStream:
          # Flush queue and prepare all buffers for revoking
        m_dataStream.Flush(peak.DataStreamFlushMode_DiscardAll)
 
          # Clear all old buffers
        for buffer in m_dataStream.AnnouncedBuffers():
            m_dataStream.RevokeBuffer(buffer)
 
        payload_size = m_node_map_remote_device.FindNode("PayloadSize").Value()
 
          # Get number of minimum required buffers
        num_buffers_min_required = m_dataStream.NumBuffersAnnouncedMinRequired()
 
          # Alloc buffers
        for count in range(num_buffers_min_required):
            buffer = m_dataStream.AllocAndAnnounceBuffer(payload_size)
            m_dataStream.QueueBuffer(buffer)
 
        return True
  except Exception as e:
      # ...
    str_error = str(e)
    print("Error by allocating buffers")
    print(str_error)
    return False
 
 
def start_acquisition():
  print("Start acquisition")

  try:
    m_dataStream.StartAcquisition(peak.AcquisitionStartMode_Default, peak.DataStream.INFINITE_NUMBER)
    m_node_map_remote_device.FindNode("TLParamsLocked").SetValue(1)
    m_node_map_remote_device.FindNode("AcquisitionStart").Execute()
       
    return True
  except Exception as e:
      # ...
      str_error = str(e)
      print(str_error)
      return False

def saving_acquisition():  
  fourcc = cv2.VideoWriter_fourcc('W','M','V','2')
  out = cv2.VideoWriter( "video", fourcc, 50, (1936,  1096))
  while True:
    try:
      
      # Get buffer from device's DataStream. Wait 5000 ms. The buffer is automatically locked until it is queued again.
      buffer = m_dataStream.WaitForFinishedBuffer(5000)

      image = ids_peak_ipl_extension.BufferToImage(buffer)
        
      # Create IDS peak IPL image for debayering and convert it to RGBa8 format
            
      image_processed = image.ConvertTo(ipl.PixelFormatName_BGR8)
      # Queue buffer again
      m_dataStream.QueueBuffer(buffer)
        
      image_python = image_processed.get_numpy_3D()

      frame = image_python
    
      out.write(frame)
      cv2.imshow('videoview',frame)
      
      key = cv2.waitKey(1)
      if key == ord('q'):
        break

      
    except Exception as e:
      # ...
      str_error = str(e)
      print("Error by saving acquisition")
      print(str_error)
      return False

 
def main():
  
  # initialize library
  peak.Library.Initialize()
 
  if not open_camera():
    # error
    sys.exit(-1)
 
  if not prepare_acquisition():
    # error
    sys.exit(-2)
 
  if not alloc_and_announce_buffers():
    # error
    sys.exit(-3)
 
  if not start_acquisition():
    # error
    sys.exit(-4)

  if not saving_acquisition():
    out.release()
    cv2.destroyAllWindows()
    print("oke")
    # error
 
  peak.Library.Close()
  print('executed')
  sys.exit(0)
 
if __name__ == '__main__':
  main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM