嵌入式linux驱动红外mlx90640并显示数据

问题描述

在嵌入式linux平台上开发QT程序时,采集和显示红外的数据。
我使用的开发环境是正点原子的imx6ull的出厂系统,红外模块是mlx90640,使用opencv将采集到的红外图像显示出来,使用opencv制作界面。
关键词:QT,linux,mlx90640,opencv

问题解决

  1. 获取红外图像
    1. 参考链接1,将链接1正确编译后挂载驱动就可以获得温度原始数据从串口中打印出来
  2. 使用opencv将串口原始数据填入cv ::Mat,参考链接3,再将cv:Mat转换为可以在Opencv中显示的QImage,参考链接2
    1. 重点修改的转换代码如下,也就是将串口打印更换为输出QImage供QT调用
	
	QImage Mlx90640::MLX90640_Show(){
    int fd = mlx90640_fd;
    uint16_t double_count = 0;
    uint16_t i=0,j=0;
    float Ta,tr;
    float emissivity=0.95;
    static float mlx90640To_Temp[768];
    static float mlx90640To[768];
    uint16_t frame[834];
    static uint16_t data[768*sizeof(float)];
    cv::Mat IR_mat(32,24, CV_32FC1, data);

    for(double_count = 0; double_count < 2;){
        if(0x00 == MLX90640_GetFrameData(fd, frame)){
            Ta = MLX90640_GetTa(frame, &mlx90640);
            tr = Ta - TA_SHIFT;
            printf("mlx90640 Ta:%f tr:%f\n",Ta,tr);
            if(0 == double_count)
                MLX90640_CalculateTo(frame, &mlx90640, emissivity, tr, mlx90640To);
            else
                MLX90640_CalculateTo(frame, &mlx90640, emissivity, tr, mlx90640To_Temp);

            if(1 == double_count){
                //merge data
                for(i = 0,j = 0;i<768;i++){
                    if(i%32 == 0 && i != 0){
                        j++;
                    }
                    if(0 == j%2 && 1 == i%2){
                        mlx90640To[i] = mlx90640To_Temp[i-1];
                    }
                    else if(1 == j%2 && 0 == i%2){
                        mlx90640To[i] = mlx90640To_Temp[i+1];
                    }
                }

                for(int y = 0; y < 24; y++){
                    for(int x = 0; x < 32; x++){
                        float val = mlx90640To[32 * y + x];
                        IR_mat.at(x,y) = val;
                    }
                }
            }
            double_count++;
        }
    }
    // Normalize the mat
    cv::Mat normal_mat;
    cv::normalize(IR_mat, normal_mat, 0,1.0, cv::NORM_MINMAX, CV_32FC1);
    IR_mat.release();
    // Convert Mat to CV_U8 to use applyColorMap
    double minVal, maxVal;
    cv::minMaxLoc(normal_mat, &minVal, &maxVal);
    cv::Mat u8_mat;
    normal_mat.convertTo(u8_mat, CV_8U, 255.0/(maxVal - minVal), -minVal);
    normal_mat.release();
    // Resize mat
//    cv::Mat size_mat;
//    cv::resize(u8_mat, size_mat, cv::Size(240,320), cv::INTER_CUBIC);

    // Apply false color
    cv::Mat falsecolor_mat;
//    cv::applyColorMap(size_mat, falsecolor_mat, cv::COLORMAP_JET);
//    size_mat.release();
    cv::applyColorMap(u8_mat, falsecolor_mat, cv::COLORMAP_JET);
    u8_mat.release();

    const uchar *pSrc = (const uchar*)falsecolor_mat.data;
    QImage qImage(pSrc,falsecolor_mat.cols, falsecolor_mat.rows,falsecolor_mat.step,
                  QImage::Format_RGB888);

    return qImage;

}
  1. 将链接1中的驱动文件进行适配,嵌入到C++的工程文件,主要是将c文件改为c++文件,或者直接使用extern的方式进行c文件的引用(告知IDE要使用gcc进行编译)
extern "C"
{
#include "MLX90640_API.h"
}

参考链接

  1. (2条消息) rk3288 7.1 mlx90640调试_小钟同学的博客-CSDN博客_mlx90640
  2. (3条消息) QT的QImage 与 Opencv的Mat 之间的转换_dancing_night的博客-CSDN博客_opencv qimage
  3. 如何在C++通过raspberry Pi上的i2c将MLX90640热像仪图像数据导入OpenCV?- 堆栈溢出 (stackoverflow.com)

你可能感兴趣的:(linux)