當前位置: 華文世界 > 手機

一塊免費的PCB,就能讓手機秒變熱成像儀!方法很簡單

2023-12-08手機

一塊小小的免費PCB,就能 讓手機秒變熱成像儀

還是賊拉 高畫質 的那種!

總開發成本也就100元左右!

這不得圍觀一下!

一、開源描述

拋開了傳統的熱成像儀制作方式,使用 可見光camera 熱成像傳感器 制作了一個 雙目手機熱成像儀 。像素:640x480。

目前,計畫已全開源。

——這個熱成像儀的 設計原理 是什麽? 電路 如何設計? 軟體 如何設計?使用了什麽演算法和技巧?

下面一一進行分析!

二、計畫功能實作原理

了解功能原理前須知:

熱成像儀,為什麽要設計成「雙目」的?

  • 可見光相機具有分辨率高、幀率高的特點。
  • 熱成像傳感器可以測量溫度分布,但是分辨率低、幀率低。
  • 使用可見光影像來補償熱成像影像,就可以達到熱成像圖—— 品質高、分辨率高 的效果。

    那具體的功能實作是怎樣的?下面就分析一下!

    本計畫整體功能框架圖如下。

    首先MCU透過I2C介面 讀取熱成像傳感器 數據,透過USB介面 傳向USB Hub

    Camera 通用免驅USB網路攝影機,也 接到USB Hub上面

    然後將Usb Hub和Android手機連線。

    接著,Android手機的套用層就會獲取到兩個傳感器的數據。

    透過一定演算法進行融合,就能得到——分辨率較高、品質較好的熱成像圖!

    這是 熱水壺 熱量分布圖:

    這是 白天公園 的熱量分布圖:

    這是 夜間街道 的熱量分布圖:

    想實作這樣的效果,軟硬體該如何設計呢?

    三、硬體設計原理

    原理圖

    PCB圖

    本章會將原理圖拆分為5部份,一一說明一下。

    1.MCU

    MCU使用的是STM32F411CEU6,帶USB FS,其帶浮點運算單元可對熱成像數據進行解算。

    2.USB Hub

    USB Hub使用的是SL2.1A,支持USB HS,可以用於傳輸網路攝影機數據。此處接了晶振,可不焊接。

    Camera則透過焊接方式連線到CAM_DM/CAM_DP。

    USB1是一個USB TypeC公頭,用於連線手機。

    3.熱成像傳感器

    熱成像傳感器使用的是MLX90640。

  • 分辨率:32x24像素;
  • I2C介面最高速率:1MHz。
  • 4.電源

    電源這裏直接使用了一塊LDO進行穩壓,型號是ME6211。

    可以 直接用低ESR的陶瓷電容 進行輸入輸出的穩壓

    5.其他

    電源燈和測試LED電路:


    偵錯SWD介面:


    測試點,固件使用UART2作為Debug串口:

    完成了硬體部份的設計,咱們再深入剖析一下,軟體部份的核心演算法是什麽!

    四、軟體設計原理

    軟體部份,將重點分析——軟體設計思路、Android APP設計、數據融合演算法,這三個部份。

    1.軟體設計思路

    開發環境使用STM32CubeIDE。

    軟體整體設計框架圖如下:

    透過I2C從mlx90640讀取數據,進行打包,再使用USB發送讀取到的數據。

    整個過程使用一個迴圈即可。

    其中mlx90640的 溫度測量範圍是 -40到300攝氏度

    值得註意的是:

    溫度測量範圍需要保留兩位小數,轉換為整型為-4000到30000,也可以用16位元整型覆蓋,使用一個0x8000為起始碼,後續跟768個溫度數據。

    mlx90640官方已經提供驅動, 只需要實作對應I2C的讀寫操作 ,即可透過API來讀取傳感器數據。

    USB庫由CubeIDE自動生成 ,直接呼叫USBCDC發送數據即可。

    2.Android APP

    Android端主要負責——數據讀取、融合和顯示功能的實作。

    這裏有兩個USB裝置:

  • 一個是USB串口,用於傳輸熱成像數據;
  • 一個是USB網路攝影機,用於傳輸影像數據。
  • ①軟體框架

    Camera和熱成像傳感器的數據讀取都有對應的庫支持。

    由於兩個庫對數據的讀取都是用的異步回呼的方式,因此這裏采用雙buffer緩存的機制

    就以Camera為例,解析一下數據讀取的邏輯:

    初始化一個長度為2的佇列 。回呼發生時,就新申請一塊buffer,然後將YUV數據拷貝到這塊buffer中,再將這塊buffer放入佇列。

    起一個執行緒 ,不斷從佇列中讀取數據,用於數據融合。

    如果執行緒讀取太慢 ,回呼發現佇列已經滿,則從佇列中取出一塊buffer丟棄,然後再將新的buffer放入佇列。

    如果回呼一直不來 ,執行緒佇列為空,則跳過下一次再讀取。因為每一次回呼都會新申請一塊buffer,因此buffer不存在並行問題。

    佇列添加和刪除 存取的都是同一個數據結構,存在並行問題, 操作時需要註意上鎖

    如上所述,Camera有兩個佇列:

  • 一個存放YUV數據;
  • 一個存放熱成像數據。
  • 只透過一個執行緒來存取兩個佇列。兩個佇列都有數據時才取出,並進行數據融合。

    由此我們得出,軟體總體執行流程如下:

    ②Camera數據讀取和預覽

    Android對網路攝影機的支持使用 UVCAndroid

    該庫基於saki4510t/UVCCamera開發,提供了更為簡單的介面。

    ③熱成像數據讀取和預覽

    熱成像數據透過USBCDC傳輸,在Android端看到的是一個虛擬串口。

    Android開發環境中,主要使用 felHR85/UsbSerial 提供虛擬串口的操作支持,並在回呼中將熱成像數據放入佇列中。

    3.數據融合

    上面提到過多次「數據融合」。

    那麽,要如何獲取數據,並進行融合呢?

    ①獲取數據

    使用一個執行緒即可獲取數據。

    這裏預計可見光相機的幀率會比熱成像幀率更高。

    因此在等待mYUVQueue佇列有數據時才會進行數據融合。

    當 mThermalQueue 沒有數據時,則預設使用上一幀的數據。

    ②融合演算法

    這裏網路攝影機采集的是可見光的影像,分辨率是640x480;

    熱成像采集的是溫度分布,分辨率是32x24。

    融合演算法的目的是 ——透過參考可見光的影像, 讓熱成像采集的溫度影像 分辨率更高, 擁有更多的細節

    該演算法基於一個假設: 顏色相近的像素,大機率來自同一個物體,對應的溫度也應該相近。

    該演算法的流程如下:

    將熱成像溫度的分布,透過線性插值擴大到640x480像素。

    以當前像素點為中心,選定一個長寬為REF_LEN的方形區域。

  • 假設當前camera像素的亮度值為v;
  • 方形區域中每個camera像素的亮度值為v_i;
  • 每個thermal像素的亮度值為t_i。
  • 計算當前像素和參考區域每個像素的差值delta_v_i。
  • 計算系數矩陣,系數表示每個像素的權重。

  • 當delta_v_i >= 0時,k_i = 1 - delta_v_i / 255;
  • 當delta_v_i < 0時,k_i = 1 + delta_v_i / 255。
  • 計算估計值矩陣,表示每個像素相對於當前像素溫度的估計值,t_hat_i = k_i * t_i。

    計算估計值矩陣的平均值,即當前像素的溫度估計值。

    由以上演算法可知,在參考值矩陣中,與當前像素值 色度差值越小 ,對應的 系數k_i也就越大 ,對應 溫度的估計值也就越大 ,對應的估計的 溫度也就越接近

    舉個栗子。

    使用如下兩個圖片進行本地仿真。

    第一張 camera拍的 圖片, 第二張 熱成像獲取的 經過插值放大後的溫度分布圖片。分辨率均為640x480。

    當REF_LEN = 4時,融合結果如下:


    當REF_LEN = 7時,融合結果如下:

    可見, 加入融合演算法之後 ,原本插值放大的低頻資訊中, 多出了一些高頻細節

    色彩對映

    完成一個熱成像儀的最後一步,就是將融合後的影像轉為偽彩色,再按照YUV的方式對映到camera影像中。

    最終效果如下:

    因為色彩對映的原因,原本熱成像融合出的高頻細節被淹沒在海量的camera影像細節中,因此影像融合演算法的效果並不明顯,後續可能會分為兩種模式分別進行輸出。

    參考資料:

    [1]https://oshwhub.com/colourfate/binocular_thermal_imager

    — 完 —

    嘉立創EDA·頭條號

    關註我,看一手優質開源計畫