• 数字图像EXIF信息之Jhead


    前言

    在OpenCV相机标定中,有如下公式:
    projection

    其中 fx,fy 是以像素表示的焦距,属于相机内参的一部分。
    一般可通过相机标定,估计相机内参。此外还有一种方式进行估计,公式如下:

    focal_length_in_pixels=(image_width_in_pixels)(focal_length_in_mm)/(CCD_width_in_mm)

    上式很容易理解,即已知图片的宽度,焦距的实际尺寸(mm)以及CCD的宽度大小(mm),即可计算出以像素表示的焦距,通常情况下, fx,fy 相差无几,可近似相等。 这种计算内参的方式常用于3D Reconstruction。

    现在问题来了,图像的大小这个获取很简单,那怎么获得焦距以及CCD宽度以mm为单位的尺寸呢?


    EXIF

    EXIF, 是可交换图像文件的缩写,全称Exchangeable image file format。是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。EXIF可以附加于JPEG、TIFF、RIFF等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。

    也就是说,当使用数码相机或者手机拍照获得的图片,都会包含EXIF信息。现在的问题是需要一个EXIF信息的读取工具。


    Jhead

    读取EXIF的工具很多,其中Jhead算是功能够用,极易简单的工具了。很多其他工具也是基于它而开发。
    Jhead webpage

    其官网上提供可执行程序,可直接使用。运行效果如图:
    Jhead

    为了使用更方便灵活,重新封装其代码,生成Lib库文件,方便外部程序调用。

    头文件定义如下:

    //Jheadlib.h
    #ifndef _JHEADLIB_HPP__
    #define _JHEADLIB_HPP__
    #pragma once
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
        //Jhead Version 
        char* jhead_version();
        //ShowInfo = 0,不输出图片信息
        // ShowInfo = 1, 输出图片信息
        void readJpgExifInfo(char * FileName, int ShowInfo);
    
        char* getJpgName();
    
        //Jpg File Size
        unsigned int getJpgSize();
    
        //Camera Make
        char * getCamMake();
    
        char * getCamModel();
    
        char * getDateTime();
    
        int getWidth();
    
        int getHeight();
    
        float getFocalLength();
    
        float getCCDWidth();
    
        float getExposureTime();
    
        float getAperture();
    
        float getDistance();
    
        int   getJpgQuality();
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    

    其中,readJpgExifInfo为获取图片信息的唯一入口,get*()函数为获取对应的图片信息。

    主函数调用方式如下:

    // main.c
    
    #include "stdafx.h"
    #include "../Jlib/jheadLib.h"
    
    #include <stdio.h>
    
    #ifdef _DEBUG
    #pragma comment(lib, "../Debug/Jlib.lib")
    #else
    #pragma comment(lib, "../Release/Jlib.lib")
    #endif // _DEBUG
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        char* ch = jhead_version();
    
        printf("Jhead Versin 	: %s
    ",ch);
    
        if(argc < 2)
        {
            printf("Usage: JheadDemo filename(*.jpg). 
    ");
            return -1;
        }
    
        readJpgExifInfo(argv[1],1);
        printf("======================================
    ");
    
        printf("File Name 	: %s
    ",getJpgName());
        printf("Camera Model 	: %s
    ",getCamModel());
    
        printf("Resolution 	: %d x %d
    ",getWidth(),getHeight());
        printf("Focal Length 	:%4.1fmm
    ",getFocalLength());
        printf("CCD Width 	: %4.2fmm
    ",getCCDWidth());
    
        return 0;
    }

    运行结果如图:
    jlib
    由此,我们可以获得图像的宽度,焦距(mm),以及CCD宽度,使用起来很方便。

    通常情况,这里获取到的ccd的宽度是不太准确或者有时图片不包含CCD相关信息,这时候就需要我们通过网络查询了。那怎么查询呢?

    这里我们可以获得相机的型号信息,即Camera model。对于数码相机,我们可以很容易查到对应得CCD尺寸,一般该尺寸是对角线长度,单位为英寸,例如,Canon A10 的CCD尺寸为1/2.7” 。根据传感器尺寸对照表,可得出CCD的宽高尺寸为:5.27mm * 3.96mm。

    CCD

    因此,根据开头公式,即可计算出焦距对应的像素尺寸:

    focal_length_in_pixel = 640* 5.4 / 5.27 = 655.79 pixels

    库文件见个人资源

  • 相关阅读:
    CF D. Ehab and the Expected XOR Problem 贪心+位运算
    luogu 1903 [国家集训队]数颜色 / 维护队列 带修改莫队
    Test 1 T2 B 线段树合并
    CF812C Sagheer and Nubian Market 二分+贪心
    CF804B Minimum number of steps
    CF796D Police Stations BFS+染色
    CF796C Bank Hacking 细节
    k8s节点NotReady问题处理
    Elastic-Job快速入门
    Elastic-Job介绍
  • 原文地址:https://www.cnblogs.com/brother-louie/p/13976563.html
Copyright © 2020-2023  润新知