LJMUAstroecology / flirpy

Python library to interact with FLIR camera cores
Other
193 stars 54 forks source link

Can't capture image on raspberry pi #30

Closed csedwar closed 4 years ago

csedwar commented 4 years ago

Installed via pip install flirpy - appears to have installed with no issues, though manually needed to install exiftools. Is this related to bug #29?

It appears that all the tests pass when I run the pytest suite as described. But when I run the following example code:

from flirpy.camera.lepton import Lepton camera = Lepton() img=camera.grab() camera.close()

I receive this warning on he command line: [ WARN:0] global /tmp/pip-wheel-1xaftst0/opencv-python-headless/opencv/modules/videoio/src/cap_v4l.cpp (893) open VIDEOIO(V4L2:/dev/video1): can't open camera by index

in my jupyter noebook I get this error

TypeError Traceback (most recent call last)

in 2 3 camera = Lepton() ----> 4 img=camera.grab() 5 camera.close() ~/.local/lib/python3.7/site-packages/flirpy/camera/lepton.py in grab(self, device_id, telemetry_mode, strip_telemetry) 154 155 if self.cap is None: --> 156 self.setup_video(device_id) 157 158 res, image = self.cap.read() ~/.local/lib/python3.7/site-packages/flirpy/camera/lepton.py in setup_video(self, device_id) 110 # The order of these calls matters! 111 self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*"Y16 ")) --> 112 self.cap.set(cv2.CAP_PROP_CONVERT_RGB, False) 113 114 def decode_telemetry(self, image, mode="footer"): TypeError: Argument 'value' must be double, not bool
csedwar commented 4 years ago

simply not live yet in the pip repo. fixed by cloning the git repo and doing a pip install .

jveitchmichaelis commented 4 years ago

Should be pushed now, sorry about that! v0.2.3

csedwar commented 4 years ago

No worries at all! This toolkit is great. It is already saving me a ton of time. Everything else out there is so painful!

Eventually I want to capture data from ~4-6 leptons and tag it with a GPS, so am awaiting the list enumeration as well! If I get a little time i'll take a stab at it.

If you have suggestions for methods to do this efficiently and write out the data I'd be all ears. It appears there is some exif support here but its not super clear to me how to use it just yet.

jveitchmichaelis commented 4 years ago

List enumeration in principle is easy, I've just not gotten around to it. The code now should be able to find all devices with a particular USB VID/PID, so it's just a matter of matching those to the devices returned by V4L (or DShow). Rather than picking the first device, just return a list. Something along the lines of:

        @classmethod
    def find_video_devices(self):
        """
        Attempts to automatically detect which video device corresponds to the PureThermal Lepton by searching for the PID and VID.
        Returns
        -------
            int
                device number
        """

        valid_dev = []

        if sys.platform.startswith('win32'):
            device_check_path = pkg_resources.resource_filename('flirpy', 'bin/find_cameras.exe')
            device_id = int(subprocess.check_output([device_check_path, "PureThermal"]).decode())

            if device_id >= 0:
                return [device_id]

        elif sys.platform == "darwin":
            output = subprocess.check_output(["system_profiler", "SPCameraDataType"]).decode()
            devices = [line.strip() for line in output.decode().split("\n") if line.strip().startswith("Model")]

            device_id = 0

            for device in devices:
                if device.contains("VendorID_1E4E") and device.contains("ProductID_0100"):
                    return [device_id]

        else:
            import pyudev

            context = pyudev.Context()
            devices = pyudev.Enumerator(context)

            path = "/sys/class/video4linux/"
            video_devices = [os.path.join(path, device) for device in os.listdir(path)]
            dev = []

            for device in video_devices:
                udev = pyudev.Devices.from_path(context, device)

                try:
                    vid= udev.properties['ID_VENDOR_ID']
                    pid = udev.properties['ID_MODEL_ID']

                    if vid.lower() == "1e4e" and pid.lower() == "0100":
                        dev.append(int(device.split('video')[-1]))
                except KeyError:
                    pass

            # For some reason multiple devices can show up
            # and checking V4L2 capabilities is not foolproof,
            # so check we can actually capture
            for d in dev:
                cam = cv2.VideoCapture(d + cv2.CAP_V4L2)
                data = cam.read()
                cam.release()

                if data[0] == True and data[1] is not None:
                    valid_dev.append(d)

        return valid_dev

Give that a go - I don't have a camera with me right now, but there shouldn't be any big bugs ;) It just returns and checks all devices instead of just returning the first one. You can loop through the list and make a Lepton object for each dev id.

On the Lepton it should be as simple as running the code above and then making a bunch of Lepton objects. For cameras like the Boson it's a bit more difficult because we also need to make sure that we connect to the correct serial port for each camera. But the Lepton right now doesn't have any user-accessible controls in Flirpy, so you can just return a list.

Writing data really depends on what sort of frame rates you're working with. Leptons are only 9Hz and the images are quite small, so you could just store them as single files. FLIR stores sequences as stacks (literally SEQ=sequence) of images with some header information. If you store your images as 16-bit (radiometric) TIFFs then you can add geotags in the EXIF, that's probably what I'd recommend. You can use whatever encoding you feel like, e.g. store the pixel values in Kelvin*100 which gives you a max temp of around 300C.

csedwar commented 4 years ago

Yeah adding geotags to the tiff is what I was thinking. Perhaps a multiband tiff for each lepton. Frame rates are slow. 1 set in 1 second or so.

Thanks for the thoughts!

On Sep 30, 2020, at 10:10 AM, Josh Veitch-Michaelis notifications@github.com wrote:

 List enumeration in principle is easy, I've just not gotten around to it. The code now should be able to find all devices with a particular USB VID/PID, so it's just a matter of matching those to the devices returned by V4L (or DShow).

Writing data really depends on what sort of frame rates you're working with. Leptons are only 9Hz and the images are quite small, so you could just store them as single files. FLIR stores sequences as stacks (literally SEQ=sequence) of images with some header information. If you store your images as 16-bit (radiometric) TIFFs then you can add geotags in the EXIF, that's probably what I'd recommend. You can use whatever encoding you feel like, e.g. store the pixel values in Kelvin*100 which gives you a max temp of around 300C.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or unsubscribe.