Skip to content

Top

Flir Lepton 3.5

Flir Lepton 3.5 + Raspberry Pi 3でサーモグラフィー

出来上がり

サーモグラフィー画像

準備物

  • Raspberry Pi 3 Model B
  • Flir Lepton 3.5
  • FLIR Lepton Breakout Board v1.4
  • メス-メス ジャンパワイヤ
  • Raspberry Pi Camera Module V2

配線

以下の通り配線する

CS -> Pin 24, CE0 or Pin 26, CE1
MOSI -> Pin 19, MOSI
MISO -> Pin 21, MISO
CLK -> Pin 23, CLK
GND -> Pin 25, GND
VIN -> Pin 1, 3V3
SDA -> Pin 3, SDA
SCL -> Pin 5, SCL

Raspberry Pi準備

1. NOOBS等でRaspbianをインストール

2. CameraとSSHとSPIとI2Cを有効にする

1
2
$ sudo raspi-config
$ sudo reboot

3. パッケージを最新にする

1
2
$ sudo apt-get update && sudo apt-get upgrade
$ sudo reboot

4. スリープを無効に

1
2
3
4
5
6
$ sudo vi ~/.config/lxsession/LXDE-pi/autostart

@xset s 0 0
@xset s noblank
@xset s noexpose
@xset dpms 0 0 0

5. swap領域増加

1
2
3
4
5
6
7
$ sudo vi /etc/dphys-swapfile
CONF_SWAPSIZE=2048
CONF_MAXSWAP=2048

設定を反映  
$ sudo service dphys-swapfile stop
$ sudo service dphys-swapfile start

6. おまじない

1
2
3
4
$ sudo vi /boot/cmdline.txt

先頭に記載  
spidev.bufsiz=131072

7. pythonとpython-opencvを入れる

1
2
$ sudo apt-get install -y python3-dev
$ sudo apt-get install -y python-opencv

8. OpenCVを入れる(すごい時間掛かる)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.3.0.zip
$ unzip opencv.zip
$ wget -O opencv_contrib.zip https://github.com/Itseez/opencv_contrib/archive/3.3.0.zip
$ unzip opencv_contrib
$ cd opencv-3.3.0/
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_PYTHON_EXAMPLES=ON -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.3.0/modules -D BUILD_EXAMPLES=ON ..
$ make -j4
$ sudo make install
$ sudo ldconfig

9. pyleptonを入れる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
branchはlepton3-dev

$ git clone https://github.com/groupgets/pylepton.git
$ cd pylepton/
$ git checkout lepton3-dev
$ sudo python setup.py install
$ pylepton_overlay -a 200
or
$ pylepton_overlay -a 200 -d "/dev/spidev0.1"

ノイズだらけ。whileループ内にsleepを入れるとやや落ち着く

10. mylepton.py

1
$ python mylepton.py -d "/dev/spidev0.1" -H 70 -L 10 -a 0.5

mylepton.py

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# -*- coding: utf-8 -*-

import os
import cv2
import io
import numpy as np
import picamera
import time
import traceback
from pylepton.Lepton3 import Lepton3

def setColorBar(lepton_buf, _low, _high):

    d = (_high - _low) / 120.0
    i = 0 
    for i in range(120):
        if i == 0:
            continue
        if i == 119:
            break
        _d = d * i
        lepton_buf[i][152] = _high - int(_d)
        lepton_buf[i][151] = _high - int(_d)
        #print("%d,%d" % (i,lepton_buf[i][152]))

def main(alpha = 0.5, device = "/dev/spidev0.0", high = 70, low = 10):

    alpha = float(alpha)
    high  = int(high)
    low   = int(low)

    if high < low:
        exit

    _high = int(high) * 100 + 27315
    _low  = int(low)  * 100 + 27315

    stream = io.BytesIO()

    cv2.namedWindow('image', cv2.WND_PROP_FULLSCREEN)
    cv2.setWindowProperty('image', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

    lepton_buf = np.zeros((120, 160, 1), dtype=np.uint16)

    with picamera.PiCamera() as camera:
        camera.resolution = (640, 480)
        camera.framerate  = 10
        try:
            with Lepton3(device) as l:
                last_nr = 0

                while True:
                    lepton_buf, nr = l.capture()
                    if nr == last_nr:
                        k = cv2.waitKey(1)
                        if k==27:
                            break
                        continue

                    stream.seek(0)
                    camera.capture(stream, format='jpeg')
                    data = np.fromstring(stream.getvalue(), dtype=np.uint8)
                    image = cv2.imdecode(data, 1)
                    #im = image[38+18:38+18+384, 51+35:51+35+512]
                    #image = cv2.resize(im, (640, 480))

                    last_nr = nr

                    # error skip
                    data_1d = lepton_buf.ravel()
                    if np.min(data_1d) == 0:
                        k = cv2.waitKey(1)
                        if k==27:
                            break
                        continue

                    # backup for temperature
                    lepton_temp = np.copy(lepton_buf)

                    # for color bar
                    lepton_buf = np.clip(lepton_buf, _low, _high)
                    setColorBar(lepton_buf, _low, _high)

                    cv2.normalize(lepton_buf, lepton_buf, 0, 65535, cv2.NORM_MINMAX)
                    np.right_shift(lepton_buf, 8, lepton_buf)

                    h, w, _ = image.shape
                    _image  = np.asarray(image, np.uint8)
                    _lepton = np.asarray(lepton_buf, np.uint8)
                    _lepton_gray = cv2.cvtColor(_lepton, cv2.COLOR_GRAY2RGB)
                    _lepton_gray = cv2.resize(_lepton_gray, (w, h))
                    _lepton_gray = cv2.applyColorMap(_lepton_gray, cv2.COLORMAP_JET)
                    res = cv2.addWeighted(_image, alpha, _lepton_gray, 1.0 - alpha, 0)

                    h = 2
                    w = 2
                    x1 = 160 / 4 * 1 - w
                    y1 = 120 / 4 * 1 - h 
                    x2 = 160 / 4 * 3 - w
                    y2 = 120 / 4 * 1 - h
                    x3 = 160 / 4 * 2 - w  
                    y3 = 120 / 4 * 2 - h 
                    x4 = 160 / 4 * 1 - w 
                    y4 = 120 / 4 * 3 - h
                    x5 = 160 / 4 * 3 - w
                    y5 = 120 / 4 * 3 - h

                    cv2.rectangle(res, (x1 * 4, y1 * 4), ((x1 + w) * 4, (y1 + h) * 4), (0, 255, 0), -1)
                    cv2.rectangle(res, (x2 * 4, y2 * 4), ((x2 + w) * 4, (y2 + h) * 4), (0, 255, 0), -1)
                    cv2.rectangle(res, (x3 * 4, y3 * 4), ((x3 + w) * 4, (y3 + h) * 4), (0, 255, 0), -1)
                    cv2.rectangle(res, (x4 * 4, y4 * 4), ((x4 + w) * 4, (y4 + h) * 4), (0, 255, 0), -1)
                    cv2.rectangle(res, (x5 * 4, y5 * 4), ((x5 + w) * 4, (y5 + h) * 4), (0, 255, 0), -1)

                    lepton_temp1 = lepton_temp[y1:y1+h, x1:x1+w]
                    lepton_temp2 = lepton_temp[y2:y2+h, x2:x2+w]
                    lepton_temp3 = lepton_temp[y3:y3+h, x3:x3+w]
                    lepton_temp4 = lepton_temp[y4:y4+h, x4:x4+w]
                    lepton_temp5 = lepton_temp[y5:y5+h, x5:x5+w]

                    tmp1 = (np.max(lepton_temp1.ravel()) - 27315) / 100.0
                    tmp2 = (np.max(lepton_temp2.ravel()) - 27315) / 100.0
                    tmp3 = (np.max(lepton_temp3.ravel()) - 27315) / 100.0
                    tmp4 = (np.max(lepton_temp4.ravel()) - 27315) / 100.0
                    tmp5 = (np.max(lepton_temp5.ravel()) - 27315) / 100.0

                    cv2.putText(res, str(tmp1), (x1 * 4 - 40, y1 * 4 + 40), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255))
                    cv2.putText(res, str(tmp2), (x2 * 4 - 40, y2 * 4 + 40), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255))
                    cv2.putText(res, str(tmp3), (x3 * 4 - 40, y3 * 4 + 40), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255))
                    cv2.putText(res, str(tmp4), (x4 * 4 - 40, y4 * 4 + 40), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255))
                    cv2.putText(res, str(tmp5), (x5 * 4 - 40, y5 * 4 + 40), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255))

                    j = 10
                    d = (high - low) / 5.0
                    for i in range(6):
                        _d = d * i
                        _m = "-" + str(high - int(_d))
                        _n = j + (i * 92)
                        cv2.putText(res, _m, (610,  _n), cv2.FONT_HERSHEY_COMPLEX, 0.4, (255,255,255))

                    cv2.imshow('image', res)
                    k = cv2.waitKey(33)
                    if k==27:    # Esc key to stop
                        break
                    if k==ord('s'):
                        cmd = "scrot"
                        os.system(cmd)
        except Exception:
            traceback.print_exc()
        finally:
            camera.close()

if __name__ == '__main__':
    from optparse import OptionParser

    usage = "usage: %prog [options] output_file[.format]"
    parser = OptionParser(usage=usage)
    parser.add_option("-a", "--alpha",  dest="alpha",  default=0.5,              help="set lepton overlay opacity")
    parser.add_option("-d", "--device", dest="device", default="/dev/spidev0.0", help="specify the spi device node (might be /dev/spidev0.1 on a newer device)")
    parser.add_option("-H", "--high",   dest="high",   default=70,               help="highest value on display")
    parser.add_option("-L", "--low",    dest="low",    default=10,               help="lowest value on display")

    options = parser.parse_args()[0]

    main(alpha = options.alpha, device = options.device, high = options.high, low = options.low)