硬解jpeg的exif信息

关于图片文件旋转JPEG与EXIF信息 关于图片文件旋转JPEG与EXIF信息 比如某相机拍摄出来的相片,文件分辨率比如宽度7360像素,高度4912像素 十进制表示为 DEC : 7360 * 4912 十六进制则为 HEX : 1CC0 * 1330 默认情况下,会在00000030:07标志位(不同设备或程序生成的图片的标志位会有所不同,由EXIF内容而定)上存放01值表示原始文件的位置,无论这张图是横着拍的还是坚着拍的,初... 阅读详情
AI摘要

本文探讨了使用C++标准库直接读取JPEG图像的Exif信息,介绍了Exif数据结构,如IFD(ImageFileDirectory)和XMP元数据,以及如何通过解析APP0和APP1区域来提取Exif数据,包括相机制造商、分辨率等信息。

当前有很多库能硬解jpeg图像信息,但如果是硬解呢,不依赖其他图形库,只通过c++标准库进行读取可行吗。

jpeg的结构

首先,我们可以参考Description of Exif file format这篇文章和JPG这篇文章,可以看出jpeg的结构基本如下:
jpeg文件结构
另一份exif的数据详细解析
Exif值解析
从这份表单可以看出,这个图片的exif信息还是很多的。但是!当我使用代码强行提取的时候,发现提取到的exif信息远小于表单上的数据!这是因为一部分图片拥有的exif信息是不完全的。

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <sstream>
#include <string>

struct ExifData {
    std::string cameraModel;
    std::string creationDate;
    int rating;
    std::string description;
    int xResolution;
    int yResolution;
    int resolutionUnit; // 1 = no-unit, 2 = inch, 3 = cm
};



// 查找和提取 Exif 数据
std::string findAndExtractExifData(const std::vector<unsigned char>& imageData) {
    // 查找 Exif 数据的开始
    std::vector<unsigned char> startMarker(2) ;
     startMarker[0] = 0xFF;
     startMarker[1] = 0xE1;
    auto startIter = std::search(imageData.begin(), imageData.end(), startMarker.begin(), startMarker.end());
    if (startIter == imageData.end()) {
        std::cout << "未找到 Exif 数据的开始" << std::endl;
        return "";
    }

    // 获取 Exif 数据的长度
    auto exifLengthIter = startIter + 2;
    unsigned short exifLength = (static_cast<unsigned short>(*(exifLengthIter)) << 8) | static_cast<unsigned short>(*(exifLengthIter + 1));
    std::cout << "Exif 数据长度: " << exifLength << std::endl;

    // 提取 Exif 数据
    std::vector<unsigned char> exifData(exifLength);
    std::copy(startIter, startIter + exifLength, exifData.begin());

    // 返回 Exif 数据的字符串形式
    return std::string(reinterpret_cast<char*>(exifData.data()), exifData.size());
}

int main() {
    // 从 JPEG 图像文件中读取数据
    std::ifstream file("your_image_path/image.jpg", std::ios::binary | std::ios::ate);
    if (!file.is_open()) {
        std::cerr << "无法打开图像文件" << std::endl;
        return 1;
    }

    std::streamsize fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    std::vector<unsigned char> imageData(fileSize);
    if (!file.read(reinterpret_cast<char*>(imageData.data()), fileSize)) {
        std::cerr << "无法读取图像文件" << std::endl;
        return 1;
    }

    // 查找并提取 Exif 数据
    std::string exifData = findAndExtractExifData(imageData);

    // 输出 Exif 数据
    std::cout << exifData << std::endl;

    return 0;
}

输出的值如下

Exif 数据长度: 2905
��
Yhttp://ns.adobe.com/xap/1.0/<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x=“adobe:ns:meta/” x:xmptk=“XMP Core 6.0.0”>
<rdf:RDF xmlns:rdf=“http://www.w3.org/1999/02/22-rdf-syntax-ns#”>
<rdf:Description rdf:about=“”
xmlns:xmp=“http://ns.adobe.com/xap/1.0/”
xmlns:dc=“http://purl.org/dc/elements/1.1/”
xmlns:tiff=“http://ns.adobe.com/tiff/1.0/”>
xmp:CreatorToolNIKON D810 Ver.1.01 </xmp:CreatorTool>
xmp:CreateDate2018:11:20 10:40:31</xmp:CreateDate>
xmp:Rating0</xmp:Rating>
tiff:XResolution300</tiff:XResolution>
tiff:YResolution300</tiff:YResolution>
tiff:ResolutionUnit2</tiff:ResolutionUnit>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta> <?xpacket end="w

其中能读出的数据有:

根节点是 <x:xmpmeta>, 其中包含了 3 个命名空间:
xmlns:x=“adobe:ns:meta/”: Adobe 自定义的 XMP 元数据命名空间
xmlns:rdf=“http://www.w3.org/1999/02/22-rdf-syntax-ns#”: RDF (Resource Description Framework) 语法命名空间
xmlns:xmp=“http://ns.adobe.com/xap/1.0/”: XMP 核心属性命名空间
xmlns:dc=“http://purl.org/dc/elements/1.1/”: Dublin Core 元数据属性命名空间
xmlns:tiff=“http://ns.adobe.com/tiff/1.0/”: TIFF 图像元数据属性命名空间

在 rdf:Description 节点中,我们可以获取到:
xmp:CreatorTool: 创建该图像的工具,是 “NIKON D810 Ver.1.01”
xmp:CreateDate: 图像的创建日期,是 “2018:11:20 10:40:31”
xmp:Rating: 图像的评分,是 “0”
tiff:XResolution: 图像的水平分辨率,是 “300”
tiff:YResolution: 图像的垂直分辨率,是 “300”
tiff:ResolutionUnit: 分辨率的单位,是 “2” (代表英寸)

这个时候,细心的朋友可能发现了,我们的有效信息一般是由 <?xpacket begin= 开始而由 <?xpacket end= 结束(事实上在结束标志前还有一大片空数据)因此实际结束位应该是一定数量的空数据或者 <?xpacket end= 知道这个信息就好办了,我们就可以用一个函数来硬解图片exif数据

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <unordered_map>

std::string extractExifData(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);

    if (!file) {
        std::cout << "无法打开文件: " << filename << std::endl;
        return "";
    }

    std::vector<char> imageData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
    file.close();

    std::string exifData;
    std::string startMarker = "<?xpacket begin=";
    std::string endMarker = "    ";

    size_t startPos = std::string(imageData.begin(), imageData.end()).find(startMarker);
    if (startPos != std::string::npos) {
        size_t endPos = std::string(imageData.begin() + startPos, imageData.end()).find(endMarker);
        if (endPos != std::string::npos) {
            endPos += startPos;
            exifData = std::string(imageData.begin() + startPos, imageData.begin() + endPos + endMarker.length() + 3);
        }
    }

    return exifData;
}

此时我们能获取到各种类型图片的内嵌xmp信息,其中就有我们需要的部分信息,只要对其中数据进行提取就可以获得数据
在这里插入图片描述

读取的值其实还不是exif图,而是内嵌的xmp文件,为妾这样读取效率太慢,这个时候,我们就可以思考有没有更佳优异的读取exif信息的方式了。
这个时候我们就要理解一个概念叫IFD,这个数据结构长12位由2位tag,2位type,4位count和4位offset组成,其中,tag是标签名,每个tag(2位16进制数)都会对应一个标签,比如0x010f就是make标签,代表相机制造商信息,具体的标签名对应列表参考这个文档Exif2.3标签名。

此时我们就可以正确读取了,以EXIF格式的jpeg为例,首先我们读取前两位是否为0xFF 0xD8,然后读取四位看是0xE0还是0xE1,如果是0xE0则是APP0区域,位JFIF空间,如果是0xE1则是APP1区域为Exif空间
Exif和Jfif对比
因此,如果是JFIF,提取数据就比较简单了,不需要考虑大小端啥的,按照维基百科-JPEG文件交换格式

JFIF文件结构如下
JFIF文件结构
APP0标记段如下
APP0
单纯读取JFIF信息就可以只读EXIF空格后的几位
而读取EXIF数据则复杂得多。
首先,用文件指针读取第一二位,确定是否为FFD8,如果是则下一步,否输出不是jpeg文件,然后读取第三四位看是FFE0还是FFE1,如果是FFE0则为JFIF格式,如果为FFE1则为EXIF格式,如果是EXIF存储格式,则读取第13和14位,看是否为II或者MM如果是II则为小端存储,MM则为大端存储,然后读取其21位和22位(此时开始读取需要遵守之前读取的大小端规则)确定总体tag数量比如刚刚读取到II,现在读取到0D00则有13个tag然后开始将数据写入IFD中。
进行完逻辑之后,我们就读取到了第一个非常有用的数据IFD( Image File Directory),然后再针对性进行解码,下面是一个示例

#include <i386/endian.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <string>

using namespace std;


// 字节序枚举
enum ByteOrder {
    LITTLE,
    BIG
};

enum DataType {
    Byte = 1,
    Ascii = 2,
    Short = 3,
    Long = 4,
    Rational = 5,
    Undefined = 7,
    SignedRational = 10,
    Float = 11,
    Double = 12
};

// IFD结构体
struct IFD {
    unsigned short tagName;
    unsigned short type;
    unsigned int count;
    unsigned int offset;
};

// 读取2个字节
unsigned short readShort(ifstream& file, ByteOrder byteOrder) {
    unsigned char bytes[2];
    file.read(reinterpret_cast<char*>(bytes), 2);
    if (byteOrder == LITTLE) {
        return (bytes[1] << 8) + bytes[0];
    } else {
        return (bytes[0] << 8) + bytes[1];
    }
}

// 读取4个字节
unsigned int readLong(ifstream& file, ByteOrder byteOrder) {
    unsigned char bytes[4];
    file.read(reinterpret_cast<char*>(bytes), 4);
    if (byteOrder == LITTLE) {
        return (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0];
    } else {
        return (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];
    }
}

// 解析IFD结构体中的标记名称和标记值
void parseIFDValue(ifstream& file, ByteOrder byteOrder, const IFD& ifd, const map<unsigned short, string>& tagNames) {
    // 输出标记名称
    if (tagNames.find(ifd.tagName) != tagNames.end()) {
        cout << "标记名称: " << tagNames.at(ifd.tagName);
    } else {
        cout << "未知标记: 0x" << hex << ifd.tagName;
    }

    // 根据类型解析标记值
    switch (ifd.type) {
            case Ascii: {
            streampos currentPos = file.tellg();
            file.seekg(ifd.offset, ios::beg);
            vector<char> buffer(ifd.count);
            file.read(buffer.data(), ifd.count);
            string value(buffer.begin(), buffer.end());
            cout << " 标记值: " << value << endl;
            file.seekg(currentPos);
        }
        break;
        case Short: {
            if (ifd.count == 1) {
                cout << " 标记值: " << ifd.offset << endl;
            } else {
                streampos currentPos = file.tellg();
                cout << " 标记值 ";
                file.seekg(ifd.offset, ios::beg);
                for (unsigned int i = 0; i < ifd.count; i++) {
                    unsigned short value = readShort(file, byteOrder);
                    cout<< value << endl;
                }
                cout << endl;
                file.seekg(currentPos);
            }
        }
        break;
        case Long: {
            if (ifd.count == 1) {
                cout << " 标记值: " << ifd.offset << endl;
            } else {
                streampos currentPos = file.tellg();
                file.seekg(ifd.offset, ios::beg);
                cout << " 标记值 ";
                for (unsigned int i = 0; i < ifd.count; i++) {
                    unsigned int value = readLong(file, byteOrder);
                    cout <<  value ;
                }
                cout << endl;
                file.seekg(currentPos);
            }
        }
        break;
        // 其他类型的处理...
        default:
            cout << "未处理的数据类型: " << ifd.type << endl;
            break;
    }
    cout << endl;
}

// 解析EXIF元数据
void parseExif(const string& filename) {
    ifstream file(filename, ios::binary);
    if (!file) {
        cout << "无法打开文件: " << filename << endl;
        return;
    }

    // 读取前两个字节,确定是否为JPEG文件
    unsigned short marker = readShort(file, BIG);
    if (marker != 0xFFD8) {
        cout << "不是JPEG文件" << endl;
        return;
    }

    // 读取下一个标记
    marker = readShort(file, BIG);
    if (marker != 0xFFE0 && marker != 0xFFE1) {
        cout << "不是JFIF或EXIF格式" << endl;
        return;
    }

    // 如果是EXIF格式,读取字节序和标记数量
    ByteOrder byteOrder;
    unsigned int ifdOffset = 0;
    if (marker == 0xFFE1) {
        file.seekg(8, ios::cur); // 跳过EXIF头
        unsigned short byteOrderMarker = readShort(file, BIG);
        cout << "字节序: " << byteOrderMarker << endl;
        if (byteOrderMarker == 0x4949) {
            byteOrder = LITTLE;
        } else if (byteOrderMarker == 0x4D4D) {
            byteOrder = BIG;
        } else {
            cout << "无效的字节序" << endl;
            return;
        }
        file.seekg(2, ios::cur); // 跳过42
        ifdOffset = readLong(file, byteOrder) + 12;
    }

    // 读取IFD
    file.seekg(ifdOffset, ios::beg);
    unsigned short tagCount = readShort(file, byteOrder);
    cout << "标记数量: " << tagCount << endl;

    // 定义标记名称映射
    map<unsigned short, string> tagNames;
    tagNames[0x010E] = "ImageDescription";
    tagNames[0x013B] = "Artist";
    tagNames[0x010F] = "Make";
    tagNames[0x0110] = "Model";
    tagNames[0x0112] = "Orientation";
    tagNames[0x011A] = "XResolution";
    tagNames[0x011B] = "YResolution";
    tagNames[0x0128] = "ResolutionUnit";
    tagNames[0x0131] = "Software";
    tagNames[0x0132] = "DateTime";
    tagNames[0x0213] = "YCbCrPositioning";
    tagNames[0x8769] = "ExifOffset";
    tagNames[0x8298] = "Copyright";
    tagNames[0x829A] = "ExposureTime";
    tagNames[0x829D] = "FNumber";
    tagNames[0x8822] = "ExposureProgram";
    tagNames[0x8825] = "GPSInfo";
    tagNames[0x8827] = "ISOSpeedRatings";
    tagNames[0x9000] = "ExifVersion";
    tagNames[0x9003] = "DateTimeOriginal";
    tagNames[0x9004] = "DateTimeDigitized";
    tagNames[0x9204] = "ExposureBiasValue";
    tagNames[0x9205] = "MaxApertureValue";
    tagNames[0x9207] = "MeteringMode";
    tagNames[0x9208] = "Lightsource";
    tagNames[0x9209] = "Flash";
    tagNames[0x920A] = "FocalLength";
    tagNames[0x927C] = "MakerNote";
    tagNames[0x9286] = "UserComment";
    tagNames[0xA000] = "FlashPixVersion";
    tagNames[0xA001] = "ColorSpace";
    tagNames[0xA002] = "ExifImageWidth";
    tagNames[0xA003] = "ExifImageLength";
    tagNames[0xA433] = "LensMake";
    tagNames[0xA434] = "LensModel";
    
    vector<IFD> ifds(tagCount);
    // 读取IFD结构体
    for (int i = 0; i < tagCount; i++) {
        ifds[i].tagName = readShort(file, byteOrder);
        ifds[i].type = readShort(file, byteOrder);
        ifds[i].count = readLong(file, byteOrder);
        ifds[i].offset = readLong(file, byteOrder) + 12;

        // // 输出IFD信息
        // if (tagNames.find(ifds[i].tagName) != tagNames.end()) {
        //     cout << "标记名称: " << tagNames[ifds[i].tagName];
        // } else {
        //     cout << "未知标记: 0x" << hex << ifds[i].tagName;
        // }
        // cout << " 类型: " << ifds[i].type ;
        // cout << " 数量: " << ifds[i].count;
        // cout << " 偏移量: " << ifds[i].offset << endl;
        // cout << endl;
        parseIFDValue(file, byteOrder, ifds[i], tagNames);
    }

    file.close();
}

解析完成就可以拿到exif数据啦
在这里插入图片描述

等等,这样我们只解析了一个区块的exif信息,要完整解析还得再获取一个偏移量获得下一区块的位置,而且如果偏移量少于tagcout*12的情况,原偏移量所在位置就是值位置,也就是说,如果偏移量为1,那么值就为1

使用libexif开源库修改jpeg相片exif信息 libexif简介 libexif是一个开源的图片exif信息操作库,提供了对exif信息常见操作接口; exif则是相片中的附属信息,常见的exif信息如图: 阅读详情

相关推荐

JPG图片叠加exif信息

<br />常见的图片格式有:<br />1、BMP格式 <br />Windows中的一各标准格式,用于存储独立于设备和应用程序的图象!所以一般的程序都很容易就可以读取BMP的图象!以象素为单位记录图片数据,每一象素可以有1、4、8、15、24、32和64位的颜色值!在文件头就给定了这些信息。24位的图片为通用的BMP文件!<br /><br />2、联合图象专家组压缩方案(JPEG) <br />JPEG压缩方案在扫描图象等自然景色方面表现很出色!某些信息在压缩的时候就丢失了!但为些往往是我们人眼所无法

自由的小鱼 2075

图像JPEG&EXIF格式介绍(一)

1、Jpeg介绍 JPEG(Joint Photographic Experts Group)是JPEG标准的产物,该标准由国际标准化组织(ISO)制订,是面向连续色调静止图像的一种压缩标准。JPEG格式是最常用的图像文件格式,后缀名为.jpg或.jpeg。 jpeg标准是在1992年被创建 2、Jpeg格式介绍 ...

zhxx120的专栏 5930

20170227. EXIF信息的说明(opencv320 ApplyExifOrientation)

在opencv3.2.0中,对imread函数做了修改 Mat imread( const String& filename, int flags ) { /// create the basic container Mat img; /// load the data imread_( filename, flags, LOAD_MAT, &img );

u014488388的专栏 2550

XPath语言

XPath语言是一门专门用于在XML文档中查找信息的语言,其他XML程序可利用XPath在XML文档中对元素和属性进行导航 我们之所以需要这个导航是因为我们的XML文档是用来存储数据的,需要将数据提取出来使用,所以通过查找标签和属性进一步获取数据 XPath节点 XPath基本概念: 基本值(或原子值): 基本值专门用于表示简单的数据值,例如整数值、字符串。我们可以把...

成长日记的博客 709

别再折腾老教程了!树莓派4B/5最新系统(Raspberry Pi OS Bookworm)红外遥控配置,用gpio-ir驱动一次成功

本文详细介绍了树莓派4B/5在最新Raspberry Pi OS Bookworm系统下配置红外遥控的完整指南,摒弃过时的lirc-rpi驱动,采用现代gpio-ir驱动方案。从硬件连接到软件配置,提供10分钟快速上手指南,涵盖驱动加载、信号测试、按键映射及高级应用场景,帮助用户高效完成红外遥控配置。

weixin_42520909的博客 442

PDS联合Modelsim仿真报错(Error loading design) line6报错 -novopt已禁用 (全网最详细!!!!!)

发现这个文档是Pango自动生成的,也就是说每一次我们点击"Run Behavior Simulation"的时候,PDS都会自动生成一次这个./run_behav_simulate.tcl文件,所以就算我们这一次把这个文件修改了,我点击"Run Behavior Simulation"想让它再跑一次正确的仿真,它此时又重新生成了这个带有-novopt的错误tcl文件,仿真依旧不能成功。问题真的是出在这里,那我们修改这个./run_behav_simulate.tcl文件就好了,但事实并非如此!

weixin_74058783的博客 3192

jpeg图片的exif信息

EXIF(Exchangeable Image File)是“可交换图像文件”的缩写,当中包含了专门为数码相机的照片而定制的元数 据,可以记录数码照片的拍摄参数、缩略图及其他属性信息。exif其实是jpeg文件的一种,遵从jpeg标准,只是在文件 头信息中增加了有关拍摄信息的内容和索引图。 JEPG文件头必须以0xFF 0xD8开头,0xFF 0xD9结尾。然后后

sl8023dxf的专栏 3756

同步辐射材料科学应用指南:从XAFS原位实验到数据处理

材料结构分析是材料研究的核心环节,但传统实验室X射线受限于能量固定、亮度不足,往往难以回答原子局域配位、非晶结构及动态演变等关键问题。同步辐射光源以高通量、连续可调、偏振可控及脉冲时间结构等特性,将材料表征从静态观察推进到原位动态追踪层次。基于X射线吸收精细结构谱(XAFS)、原位实验、X射线衍射与散射、微区成像等技术,研究人员可实现元素选择性分析、近邻原子环境解析及真实工况下的结构演变监测。本文从技术原理出发,覆盖实验方案设计、样品制备、现场对光、数据处理与常见故障排查,并结合典型应用场景,为材料科学领域

weixin_32612263的博客 171

C++ 获取整个文本内容

文件内容: <?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/"> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Descript...

老狼的专栏 1974

Qt 【window udp 高频采集丢包问题】

使用Asio + 无锁队列或者环形缓存区方案可以解决 qt udp 在window平台高速采集 (128k)丢包问题。

weixin_45397344的博客 177

LLC变压器,常见的4大问题解决方案

其中之一是当付边的绕组的匝数或层数较多的时候,层间或匝间寄生电容和付边的漏感发生一个寄生的振荡,轻载的时候,这个振铃的幅度会达到很高,导致输出电压比设计的要高许多。但当输入是低压的时候,开关频率比较低,LLC谐振回路的增益较大,因而比较容易发生变压器饱和的问题。由于LLC变压器工作在LC谐振状态,LC谐振回路有个特点就是Q值问题,在这里Q值是大于1的,因而就会有实际加在变压器上的电压要比输入电压高的问题,因而在设计变压器的时候就必须考虑到这一点,否则变压器就不是工作在你设计的磁感应强度上。

1266

exif格式及解析库easyexif使用介绍

JPEG文件以字符串"0xFFD8"开头表示图像信息开始,以字符串"0xFFD9"结尾表示图像信息结束。在JPEG文件头中有一系列"0xFF??"格式的数据段,称为"标识",用来标记JPEG文件的信息段。0xFFEXIF 数据为照片管理和后期处理提供了丰富的元数据信息。摄影爱好者可以利用 EXIF 数据分类、排序、搜索照片,并根据拍摄参数优化后期编辑。总的来说, EXIF 格式为数码摄影带来了很大的便利。详细介绍exif的基本知识以及easexif库的使用。

yueguang8的博客 2285

华为OD机试真题 新系统 - WIFI设备网络规划 (Java/Py/C/C++/Js/Go)

本文整理华为 OD 机试新系统机考真题库,涵盖高频考点精析与完整题目内容,提供 C 语言、Java、C++、Python、Go、JavaScript 多语言源码实现,搭配详细解题思路讲解,并支持在线 OJ 刷题练习,助力高效备考华为 OD 机试新系统。

算法大师! 2017

JPEG文件中的EXIF(下)

元文链接 EXIF格式介绍(下) JPEG图片中的EXIF信息是以TIFF格式保存的,关于TIFF格式的介绍,可以参考上篇。 下篇中将介绍EXIF中都保存了哪些数据,这些数据的内容和格式,最后介绍一下EXIF中的缩略图信息。 JPEG图片的EXIF数据 EXIF JPEG文件将EXIF信息存储在JFIF的APP1标记中。

萌主不萌的专栏 2959

论文工具——写论文好用的绘图工具(甘特图+流程图+网络模型图+泳道图)

* 在写HiFi-GAN论文的代码阅读过程中,我发现仅仅通过文字来描述网络结构,不够详细,所以想绘制出网络结构图,更加具象化的描述出网络结构。想去花了,才发现之前都是通过在线绘图网站画的,费时费力,所以想找一些专门的网站化出比较规范并且高质量的图。一方面是为了方便讲解,提高论文的质量,另外一方面也是为了以后写论文打下良好的基础。 * 这篇文章会根据我以前的画图经验展开,以前是使用绘图软件,手动绘图。后来,看到了其他的方法,但是需要写一些代码,或者需要安装特定的软件,投入成本太大,就没有学。所以,本文分享的工

Blackoutdragon的博客 1万+

【AutoSAR】【BootLoader】AutoSAR Bootloader 原理与流程

目录 一、HIS规范 二、BOOTLOADER软件架构 三、烧写流程 一、HIS规范 国外整车厂意识到在线刷新ECU的重要性,由奥迪公司、宝马公司、戴姆勒公司、保时捷公司、大众公司成立一个委员会,名为HIS委员会,专门负责帮助汽车制造商掌握微处理器控制单元软件和质量保证领域的原理和方法; HIS Bootloader的主要功能是通过标准的通信接口对ECU进行再编程 。 HIS Bootloader的软件设计基于AUTOSAR体系架构、ISO14229、ISO15765-2、HI...

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 5250

jpeg Exif file format  Marker APP1 简介

jpeg Exif file format Marker APP1 简介 jpeg Exif file format Marker APP1 分析 参考:Description of Exif file format Exif 文件格式与 JPEG 文件格式相同。 Exif 按照JPEG规范将图片的相关信息数据和缩略图图像插入JPEG。 因此可以使用Internet 浏览器/...

qq_38907791的博客 2146

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

EXIF信息及含义

说明: 文章内容属转载,0x的部分是代码,英文部分是EXIF规范名称,最后是数据类型。包括了数据计算说明以及某些项的数值含义,例如EXIF中色彩空间为short类型,其值是数字,代表含义为:1、黑白;2、RGB;6、YcbCr。 正文: JPEG格式和标志 JPEG文件都是以十六进制 '0xFFD8’开始,以’0xFFD9’结束。在JPEG数据中有像’0xFF**'这样的数据,这些被称为“标志”,它表示JPEG信息数据段。0xFFD8 表示SOI(Start of image 图像开始),0xFFD9表示E

Dunkle.T的博客 9193

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

JPEG系列二 JPEG文件中的EXIF(下)

https://blog.youkuaiyun.com/shelldon/article/details/54407534 EXIF格式介绍(下) JPEG图片中的EXIF信息是以TIFF格式保存的,关于TIFF格式的介绍,可以参考上篇。 下篇中将介绍EXIF中都保存了哪些数据,这些数据的内容和格式,最后介绍一下EXIF中的缩略图信息。 JPEG图片的EXIF数据 EXIF JPEG文件将EX...

子曰小玖的博客 1258

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

读取和修改JPEG图片文件的头信息EXIF和JFIF

本文链接:https://blog.youkuaiyun.com/xywy2008/article/details/38089789 1. JPEG图片格式的发展历程和简单介绍可参考下面的文章 http://en.wikipedia.org/wiki/JPEG http://blog.youkuaiyun.com/kickxxx/article/details/8173332 2. 读取JPEG图片文件头信息的工具 ...

xiatiancc的专栏 5803

获取JPEG文件中的EXIF信息旋转角度

【代码】获取JPEG文件中的EXIF信息旋转角度。

我的博客 946

JPEG Exif 学习

所有的JPEG文件以字符串“0xFFD8”开头,并以字符串“0xFFD9”结束。文件头中有一系列“0xFF??”格式的字符串,称为“标识”,用来标记JPEG文件的信息段。“0xFFD8”表示图像信息开始,“0xFFD9”表示图像信息结束,这两个标识后面没有信息,而其它标识紧跟一些信息字符。 0xFFE0 -- 0xFFEF之间的标识符称为“应用标记”,没有被常规JPEG文件利用,Exif正是

zcc1414的专栏 815

修改删除图片属性Exif信息的方法

首先下载jhead.exe文件,下载地址:http://www.sentex.net/~mwandel/jhead/jhead.exe 将下载下来的文件复制到Windows目录(这一点很重要,否则Windows会提示找不到文件)。  使用说明:  以下内容转自http://download.youkuaiyun.com/source/1791268 

zh_amin的专栏 2万+

Java 读取 JPEG 文件的 exif 信息

突然要用Java 读取 JPEG文件的信息, 宽度, 高度, 颜色表示等信息。 下载了一个工具jar 包 metadata-extractor-2.3.1.jar , 网上搜一下 放到lib 里面。 一个简单的类来读取信息 ReadFileProperties.java package com.founder.readfile; import java.io.File; import java.u

maxwellnewlife的专栏 740

jpeg exif_CompactExifLib:访问JPEG文件中的EXIF标签

Download ExifData1.1.zip - 17.9 KB 下载ExifData1.1.zip-17.9 KB 介绍 (Introduction) The EXIF standard is used by almost all photo and smartphone cameras for storing information about an image. The EXIF da...

cunhan4654的博客 724
上一篇: OpenGL实现全景图(SkyBox和Hdri双实现方式)
下一篇: 深入浅出的c++教程(基于C++Primer)第一章
可能是阿伦
博客等级 码龄7年 1424粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值