Closed jeffwitz closed 3 months ago
I have done a new example that helps to understand how to reproduce the issue and what I don't understand.
This code doesn't work :
```python from harvesters.core import Harvester import numpy as np import cv2 import time h = Harvester() h.add_file('/opt/ImpactAcquire/lib/x86_64/mvGenTLProducer.cti') h.update() ia = h.create() ia.start() ia.remote_device.node_map.ExposureTime.value = 25000 while(True): with ia.fetch() as buffer: component = buffer.payload.components[0] width = component.width height = component.height num_comp=component.num_components_per_pixel img_data = np.frombuffer(component.data,np.uint8).reshape((int(height),int(width))) cv2.namedWindow('frame', cv2.WINDOW_NORMAL) cv2.imshow('frame',img_data) if cv2.waitKey(1) & 0xFF == ord('q'): ia.stop() ia.destroy() h.reset() cv2.destroyAllWindows() cap.release() break ```
while this one works :
```python from harvesters.core import Harvester import numpy as np import cv2 import time h = Harvester() h.add_file('/opt/ImpactAcquire/lib/x86_64/mvGenTLProducer.cti') h.update() ia = h.create() ia.start() ia.remote_device.node_map.ExposureTime.value = 25000 while(True): with ia.fetch() as buffer: component = buffer.payload.components[0] width = component.width height = component.height num_comp=component.num_components_per_pixel img_data = np.frombuffer(component.data,np.uint8).reshape((int(height),int(width))) cv2.namedWindow('frame', cv2.WINDOW_NORMAL) cv2.imshow('frame',img_data) if cv2.waitKey(1) & 0xFF == ord('q'): ia.stop() ia.destroy() h.reset() cv2.destroyAllWindows() cap.release() break ```
the only difference are that the creation of the windows is within the scope of with ia.fetch() as buffer
:
cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
cv2.imshow('frame',img_data)
What I don't undersrtand is the fact that with img_data = np.frombuffer(component.data,np.uint8).reshape((int(height),int(width)))
I should have a copy so there should not have any issues with this.
Error found, np.frombuffer does not copy, you have to add the copy methode to solve it.
Perfect, thanks for the update.
I can confirm that en explicit copy of the buffer is required before it is dequeued (which is done implicitly when leaving the with ia.fetch() as buffer
block in Python)
Describe the Issue I want to implement a harvester class for crappy For now, we have gstreamer, opencv, v4l2, ximea and gphoto2 cameras available, and I want to have compatible harvester one available.
I don't succeed in getting a non corrupted buffer on my class, while it works well outside for image to image capture.
I create this code where I embed a camera class. this is basic just to try to have a workflow that is ok.
Details
```python import platform import numpy as np from crappy.camera.meta_camera import Camera import time from typing import Optional,Tuple, List, Dict, Any from crappy._global import OptionalModule try : from harvesters.core import Harvester from harvesters.util.pfnc import mono_location_formats,rgb_formats from harvesters.util.pfnc import bgr_formats from harvesters.util.pfnc import rgba_formats, bgra_formats except (ModuleNotFoundError, ImportError): harverster_exception = OptionalModule( "Harvester", "To use Genicam cameras, please install the " "harvester module : python -m pip intstall harvesters" ) class GenicamCamera(Camera): def __init__(self) -> None: super().__init__() Camera.__init__(self) self.camera = None if platform.system() == 'Windows': # Windows self.cti_file_path = 'C:/win.cti' if platform.system() == 'Linux': # Linux self.cti_file_path = ('/opt/ImpactAcquire/lib/x86_64/' 'mvGenTLProducer.cti') self.num_image = 0 self.device = None self.h = None def open(self, device: Dict[str,Any] = None, cti_file_path: str = None, **kwargs: any) -> None: self.h = Harvester() if cti_file_path is not None: self.cti_file_path = cti_file_path self.h.add_file(self.cti_file_path) self.h.update() if self.device is None: self.camera = self.h.create() else: self.camera = self.h.create(self.device) expo_time = self.camera.remote_device.node_map.ExposureTime self.camera.remote_device.node_map.ExposureTime =2500 self.camera.start() def get_image(self) -> Tuple[Dict[str, Any], np.ndarray]: if not self.camera: raise RuntimeError("Camera not opened.") buffer = self.camera.fetch(timeout=0.5) if buffer: component = buffer.payload.components[0] width = component.width height = component.height num_comp=component.num_components_per_pixel img_data = np.frombuffer(component.data,np.uint8).reshape((int(height),int(width))) buffer.queue() metadata = { 't(s)': time.time(), 'ImageUniqueID': self.num_image, } self.num_image += 1 return metadata, img_data def close(self): if self.camera: self.camera.stop() self.camera.destroy() self.h.reset() else: print("Camera is not opened or already closed.") def apply_settings(self): if self.camera and 'ExposureTime' in self.settings: self.camera.remote_device.node_map.ExposureTime.value = ( self.ExposureTime) if __name__ == '__main__': import crappy cam1 = crappy.blocks.Camera( 'GenicamCamera', config = True, # Before the test starts, displays a configuration window # for configuring the camera display_images = True, # During the test, the acquired images are # displayed in a dedicated window save_images = False, # Here, we don't want the images to be recorded # Sticking to default for the other arguments freq=100 ) crappy.start() ```
To Reproduce Steps to reproduce the behavior: in your test venv
Sample Code The main is embedded in the previous class. It takes the first camera and try to display something on the camera configurator.
Expected Behavior a real image to appear
Screenshots![image](https://github.com/genicam/harvesters/assets/11351389/50abdcf9-9711-4eac-9dc6-d9373ff25e11)
Configuration
OS: Debian 12
Python: 3.11.2
Harvester Version: 1.4.2
GenTL Producer: /opt/ImpactAcquire/lib/mvGenTLProducer.cti'
Camera: HIKROBOTS Reproducibility This phenomenon can be stably reproduced:
Actions You Have Taken Simple file without crappy that works:
Details
```python from harvesters.core import Harvester import numpy as np h = Harvester() # h.add_file('/opt/XIMEA/lib/ximea.gentl.cti') h.add_file('/opt/ImpactAcquire/lib/x86_64/mvGenTLProducer.cti') h.update() ia = h.create() ia.start() ia.remote_device.node_map.ExposureTime.value = 2500 print(f'Exposure time {ia.remote_device.node_map.ExposureTime.value}') buffer =ia.fetch(timeout = 0.5) if buffer: component = buffer.payload.components[0] width = component.width height = component.height num_comp=component.num_components_per_pixel img_data = np.frombuffer(component.data,np.uint8).reshape((int(height),int(width))) img_data1 = np.empty_like(img_data) img_data1[:] = img_data[:] buffer.queue() # Remet le buffer en queue pour réutilisation ia.stop() ia.destroy() h.reset() import matplotlib.pyplot as plt plt.imshow(img_data1,cmap='gray');plt.colorbar();plt.show() ```