2018-01-31 21:19:55 bjbz_cxy 阅读数 389
  • C++实战OpenCV3.2+QT5播放视频

    OpenCV是目前视频处理的最流行的框架,广泛用于各类项目中,并且由于OpenCV的开源特性可以很容易移植到Android、IOS和嵌入式Linux中,QT5同样是跨平台界面库的第一选择。 本次公开课将基于OpenCV3.2和QT5,详细讲解如下内容: 第一部分将讲解并分析OpenCV的视频处理接口; 第二部分将讲解 QT5如何使用OpenGL高效的绘制图像; 第三部分将讲解如何将OpenCV与QT5结合 通过本次公开课,让学员能对OpenCV的编程和QT5的界面编程 有个总体的认识,为后续继续学习奠定基础。 (1)OpenCV3.2视频接口详解? (2)OpenCV3.2 Mat图像结构详解 (3)QT5自定义Widget (4)QT5基于OpenGL绘制图像 (5)QT5月OpenCV3.2结合播放视频

    1048 人正在学习 去看看 夏曹俊

这一系列的文章都将以BMP格式图像为主做处理,主要是为了让大家能对图像处理有一个良好的认知,后面会教大家写一个能支持BMP,JPG,JPEG,PNG等格式的图像处理库。

首先你要对图像处理以及图像理论有一个基本的认识,如果没有任何基本的图像知识的话我建议先看一下博主的这篇文章:Opencv学习笔记_计算机视觉是什么?Opencv的起源 虽然说这篇文章是介绍计算机视觉和opencv的但是其中包含了很多图像理论知识。

首先第一步要对BMP图像文件格式要有一个基本的认识:

BMP图像格式详解

一.简介
BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。Windows 3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式(注:Windows 3.0以后,在系统中仍然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软极力推荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。
 
二.BMP格式结构
BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
◆ 位图文件头(bmp file header):  提供文件的格式、大小等信息
◆ 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
◆ 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
◆ 位图数据(bitmap data):图像数据区
 
BMP图片文件数据表如下:

 

数据段名称大小(byte)开始地址结束地址
位图文件头(bitmap-file header)
140000h000Dh
位图信息头(bitmap-information header)
40000Eh0035h
调色板(color table)
由biBitCount决定0036h未知
图片点阵数据(bitmap data)
由图片大小和颜色定未知未知

 

 
 
 
三.BMP文件头
BMP文件头结构体定义如下:
typedef struct tagBITMAPFILEHEADER
UINT16 bfType;        //2Bytes,必须为"BM",即0x424D 才是Windows位图文件
DWORD bfSize;         //4Bytes,整个BMP文件的大小
UINT16 bfReserved1;  //2Bytes,保留,为0
UINT16 bfReserved2;  //2Bytes,保留,为0
DWORD bfOffBits;     //4Bytes,文件起始位置到图像像素数据的字节偏移量
BITMAPFILEHEADER;
 
BMP文件头数据表如下:

 

变量名地址偏移大小作用说明
bfType0000h2Bytes
文件标识符,必须为"BM",即0x424D 才是Windows位图文件
‘BM’:Windows 3.1x, 95, NT,…  ‘BA’:OS/2 Bitmap Array  ‘CI’:OS/2 Color Icon   
‘CP’:OS/2 Color Pointer   ‘IC’:OS/2 Icon   
‘PT’:OS/2 Pointer
因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行
bfSize0002h4Bytes整个BMP文件的大小(以位B为单位)
bfReserved10006h2Bytes保留,必须设置为0
bfReserved20008h2Bytes保留,必须设置为0
bfOffBits000Ah4Bytes说明从文件头0000h开始到图像像素数据的字节偏移量(以字节Bytes为单位),以为位图的调色板长度根据位图格式不同而变化,可以用这个偏移量快速从文件中读取图像数据

 

 
 
四.BMP信息头
BMP信息头结构体定义如下:
typedef struct _tagBMP_INFOHEADER
{
DWORD  biSize;    //4Bytes,INFOHEADER结构体大小,存在其他版本I NFOHEADER,用作区分
LONG   biWidth;    //4Bytes,图像宽度(以像素为单位)
LONG   biHeight;    //4Bytes,图像高度,+:图像存储顺序为Bottom2Top,-:Top2Bottom
WORD   biPlanes;    //2Bytes,图像数据平面,BMP存储RGB数据,因此总为1
WORD   biBitCount;         //2Bytes,图像像素位数
DWORD  biCompression;     //4Bytes,0:不压缩,1:RLE8,2:RLE4
DWORD  biSizeImage;       //4Bytes,4字节对齐的图像数据大小
LONG   biXPelsPerMeter;   //4 Bytes,用象素/米表示的水平分辨率
LONG   biYPelsPerMeter;   //4 Bytes,用象素/米表示的垂直分辨率
DWORD  biClrUsed;          //4 Bytes,实际使用的调色板索引数,0:使用所有的调色板索引
DWORD biClrImportant;     //4 Bytes,重要的调色板索引数,0:所有的调色板索引都重要
}BMP_INFOHEADER;
 
BMP信息头数据表如下:

 

变量名
地址偏移
大小
作用说明
biSize
000Eh
4Bytes
BNP信息头即BMP_INFOHEADER结构体所需要的字节数(以字节为单位)
biWidth
0012h
4Bytes
说明图像的宽度(以像素为单位)
biHeight
0016h
4Bytes
说明图像的高度(以像素为单位)。这个值还有一个用处,指明图像是正向的位图还是倒向的位图,该值是正数说明图像是倒向的即图像存储是由下到上;该值是负数说明图像是倒向的即图像存储是由上到下。大多数BMP位图是倒向的位图,所以此值是正值。
biPlanes
001Ah
2Bytes
为目标设备说明位面数,其值总设置为1
biBitCount
001Ch
2Bytes
说明一个像素点占几位(以比特位/像素位单位),其值可为1,4,8,16,24或32
biCompression
001Eh
4Bytes
说明图像数据的压缩类型,取值范围为:
0         BI_RGB 不压缩(最常用)
1         BI_RLE8 8比特游程编码(BLE),只用于8位位图
2         BI_RLE4 4比特游程编码(BLE),只用于4位位图
3         BI_BITFIELDS比特域(BLE),只用于16/32位位图
4          
biSizeImage
0022h
4Bytes
说明图像的大小,以字节为单位。当用BI_RGB格式时,总设置为0
biXPelsPerMeter
0026h
4Bytes
说明水平分辨率,用像素/米表示,有符号整数
biYPelsPerMeter
002Ah
4Bytes
说明垂直分辨率,用像素/米表示,有符号整数
biClrUsed002Eh4Bytes说明位图实际使用的调色板索引数,0:使用所有的调色板索引
biClrImportant0032h4Bytes说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。

 

 
五.BMP调色板
BMP调色板结构体定义如下:
typedef struct _tagRGBQUAD
{
BYTE  rgbBlue;       //指定蓝色强度
BYTE  rgbGreen;      //指定绿色强度
BYTE  rgbRed;        //指定红色强度
 BYTE  rgbReserved;  //保留,设置为0
RGBQUAD;
 
1,4,8位图像才会使用调色板数据,16,24,32位图像不需要调色板数据,即调色板最多只需要256项(索引0 - 255)。
颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号1的颜色,接下来表示颜色号2的颜色,依此类推。
颜色表中RGBQUAD结构数据的个数有biBitCount来确定,当biBitCount=1,4,8时,分别有2,16,256个表项。
当biBitCount=1时,为2色图像,BMP位图中有2个数据结构RGBQUAD,一个调色板占用4字节数据,所以2色图像的调色板长度为2*4为8字节。
当biBitCount=4时,为16色图像,BMP位图中有16个数据结构RGBQUAD,一个调色板占用4字节数据,所以16像的调色板长度为16*4为64字节。
当biBitCount=8时,为256色图像,BMP位图中有256个数据结构RGBQUAD,一个调色板占用4字节数据,所以256色图像的调色板长度为256*4为1024字节。
当biBitCount=16,24或32时,没有颜色表。
 
五.BMP图像数据区
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,
一个扫描行所占的字节数计算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一个扫描行所占的字节数
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
位图数据的大小(不压缩情况下):
DataSize= DataSizePerLine* biHeight;
 
颜色表接下来位为位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。

通过上面的描述,我们基本上对BMP图像文件格式有一个基本的认识了,那么我们可以通过c语言的结构体的内存对齐机制来依次读取这些头文件信息,并转化成可识别的十进制信息!

首先第一步,对c语言的基本类型定义别名,方便维护。

//8bit
typedef char UINT_8;
//16bit
typedef char UINT_16[2];
//22bit
typedef char UINT_22[3];
//256bit
typedef char UINT_256[256];
//32bit
typedef int  UINT_32;
//data
typedef char* DATA;
//64 fbit
typedef double FUINT_64;
//16bit int
typedef short SUINT_16;

然后根据头信息在文件中的字节偏移地址来定义结构体:

变量名地址偏移大小作用说明
bfType0000h2Bytes
文件标识符,必须为"BM",即0x424D 才是Windows位图文件
‘BM’:Windows 3.1x, 95, NT,…  ‘BA’:OS/2 Bitmap Array  ‘CI’:OS/2 Color Icon   
‘CP’:OS/2 Color Pointer   ‘IC’:OS/2 Icon   
‘PT’:OS/2 Pointer
因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行
bfSize0002h4Bytes整个BMP文件的大小(以位B为单位)
bfReserved10006h2Bytes保留,必须设置为0
bfReserved20008h2Bytes保留,必须设置为0
bfOffBits000Ah4Bytes说明从文件头0000h开始到图像像素数据的字节偏移量(以字节Bytes为单位),以为位图的调色板长度根据位图格式不同而变化,可以用这个偏移量快速从文件中读取图像数据



变量名
地址偏移
大小
作用说明
biSize
000Eh
4Bytes
BNP信息头即BMP_INFOHEADER结构体所需要的字节数(以字节为单位)
biWidth
0012h
4Bytes
说明图像的宽度(以像素为单位)
biHeight
0016h
4Bytes
说明图像的高度(以像素为单位)。这个值还有一个用处,指明图像是正向的位图还是倒向的位图,该值是正数说明图像是倒向的即图像存储是由下到上;该值是负数说明图像是倒向的即图像存储是由上到下。大多数BMP位图是倒向的位图,所以此值是正值。
biPlanes
001Ah
2Bytes
为目标设备说明位面数,其值总设置为1
biBitCount
001Ch
2Bytes
说明一个像素点占几位(以比特位/像素位单位),其值可为1,4,8,16,24或32
biCompression
001Eh
4Bytes
说明图像数据的压缩类型,取值范围为:
0         BI_RGB 不压缩(最常用)
1         BI_RLE8 8比特游程编码(BLE),只用于8位位图
2         BI_RLE4 4比特游程编码(BLE),只用于4位位图
3         BI_BITFIELDS比特域(BLE),只用于16/32位位图
4          
biSizeImage
0022h
4Bytes
说明图像的大小,以字节为单位。当用BI_RGB格式时,总设置为0
biXPelsPerMeter
0026h
4Bytes
说明水平分辨率,用像素/米表示,有符号整数
biYPelsPerMeter
002Ah
4Bytes
说明垂直分辨率,用像素/米表示,有符号整数
biClrUsed002Eh4Bytes说明位图实际使用的调色板索引数,0:使用所有的调色板索引
biClrImportant0032h4Bytes说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。

注意这里一定要使用#pragma pack(1)告诉编译器结构体按1字节对齐(详细:详解C语言内存对齐)否则在读入文件流数据时会出现数据混淆的原因
//结构体
//图像结构体,防止结构体对齐否则读取文件流时出错,所以用pragma命令强制对齐
#pragma pack(1)  
typedef struct image_struct{
	UINT_16   image_pil;                //文件标识符  
	UINT_32   image_Size;               //文件大小  
	UINT_16   image_Reserved1;          //无需过问  
	UINT_16   image_Reserved2;          //无需过问  
	UINT_32   image_Offbits;            //头文件到图像数据偏移量  
	UINT_32   image_Stsize;             //结构体所需大小  
	UINT_32   image_Width;              //图像宽度  
	UINT_32   image_Height;             //图像高度  
	UINT_16   image_Planes;             //目标设备位面数  
	SUINT_16  image_Bitcount;           //像素点占用多少bit位  
	UINT_32   image_Compression;        //图像压缩类型  
	UINT_32   image_Sizeimage;          //图像的大小  
	UINT_32   image_Xpelspermeter;      //水平分辨率  
	UINT_32   image_Ypelspermeter;      //垂直分辨率  
	UINT_32   image_ClrUsed;            //调色板索引数  
	UINT_32   image_Clrlmportant;       //图像显示重要颜色索引数目  
	DATA      image_Data;               //图像数据 
	UINT_32   image_Data_Size;			//图像数据大小
}image; 
#pragma pack()  
下面开始写我们的第一个函数:image_load,加载图像文件
注意如果不使用c语言的内存对齐方式读取数据的话需要考虑大小端的问题,我们直接使用结构体来读取这样就不用考虑大小端的问题了,因为内存中的存储大小端与文件中是对应的!我们只需要直接读取到内存当中就行了!
//函数
//加载图像 
int image_load(struct image_struct** im, char *path){
	FILE *image_path_fp;
	image_path_fp = fopen(path, "rb");
	if (image_path_fp == NULL){
		return -1;
	}
	//取文件大小
	fseek(image_path_fp, 0, SEEK_END); //定位到文件末 
	int nFileLen = ftell(image_path_fp); //文件长度
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,防止从文件尾读取数据
	//读取头信息
	if (fread((*im), (sizeof(struct image_struct) - ((sizeof(DATA/*image_Data*/)+(sizeof(UINT_32)/*image_Data_Size*/)))/*暂不读取数据,无法从头文件中获取数据偏移量,防止数据混乱*/), 1, image_path_fp) == 0){
		return -2;
	}
	//给data变量分配内存
	(*im)->image_Data = (DATA)malloc(nFileLen-(*im)->image_Offbits/*完整的数据大小*/);
	//判断是否分配成功
	if ((*im)->image_Data == NULL){	//如果没有可用堆内存则malloc返回NULL
		return -3;
	}
	//读取数据
	//读取前将文件指针挪移到文件头信息后,找到正确的数据存储区
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,因为已经fread一次了,所以数据文件指针发生变更
	fseek(image_path_fp, (*im)->image_Offbits, SEEK_CUR);	//忽略头数据
	if (fread((*im)->image_Data, (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/), 1, image_path_fp) == 0){
		return -4;
	}
	//保存文件大小,方便读写操作
	(*im)->image_Data_Size = (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/);
	//文件指针释放,防止占用文件内核的临界资源
	fclose(image_path_fp);
	image_path_fp == NULL;
	return 0;
}
图像加载函数写完了,我们可能在使用结构体时会定义指针,所以为了方便我们在写一个用于分配内存的函数
//给图像数据分配内存
int image_malloc(struct image_struct** im){
	*im = (struct image_struct*)malloc(sizeof(struct image_struct));
	if (*im == NULL){
		return -1;
	}
	return 0;
}
还需要一个图像保存函数:
//保存图像数据到文件
int image_save_file(struct image_struct** im, char *path){
	FILE* file_fp = fopen(path, "wb+");	//以二进制可读写方式打开
	if (file_fp == NULL){	//判断文件指针是否为空
		return -1;
	}
	//写入头信息
	fwrite((*im), (*im)->image_Offbits/*直接写入头文件到数据的偏移量大小即可*/, 1, file_fp);
	//写入文件数据
	fwrite((*im)->image_Data, (*im)->image_Data_Size, 1, file_fp);
	return 0;

}
基本函数编写完成了,那么来做一个测试吧:
int main(){
	image *imga;
	image_malloc(&imga);
	image_load(&imga, "test.bmp");
	printf("图像宽度:%d\n", imga->image_Width); 
	printf("图像高度:%d\n", imga->image_Height);
	printf("图像文件占用字节:%d\n", imga->image_Size);
	printf("图像每个像素占用bit位:%d\n", imga->image_Bitcount);
	getchar();
}
完整代码:
/*Robust图像处理库
*版本:v1.0
*作者:周志豪
*4.17 19:09
*/
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
//类型定义
//8bit  
typedef char UINT_8;
//16bit  
typedef char UINT_16[2];
//22bit  
typedef char UINT_22[3];
//256bit  
typedef char UINT_256[256];
//32bit  
typedef int  UINT_32;
//data  
typedef char* DATA;
//64 fbit  
typedef double FUINT_64;
//16bit int  
typedef short SUINT_16;
//结构体
//图像结构体,防止结构体对齐否则读取文件流时出错,所以用pragma命令强制对齐
#pragma pack(1)  
typedef struct image_struct{
	UINT_16   image_pil;                //文件标识符  
	UINT_32   image_Size;               //文件大小  
	UINT_16   image_Reserved1;          //无需过问  
	UINT_16   image_Reserved2;          //无需过问  
	UINT_32   image_Offbits;            //头文件到图像数据偏移量  
	UINT_32   image_Stsize;             //结构体所需大小  
	UINT_32   image_Width;              //图像宽度  
	UINT_32   image_Height;             //图像高度  
	UINT_16   image_Planes;             //目标设备位面数  
	SUINT_16  image_Bitcount;           //像素点占用多少bit位  
	UINT_32   image_Compression;        //图像压缩类型  
	UINT_32   image_Sizeimage;          //图像的大小  
	UINT_32   image_Xpelspermeter;      //水平分辨率  
	UINT_32   image_Ypelspermeter;      //垂直分辨率  
	UINT_32   image_ClrUsed;            //调色板索引数  
	UINT_32   image_Clrlmportant;       //图像显示重要颜色索引数目  
	DATA      image_Data;               //图像数据 
	UINT_32   image_Data_Size;			//图像数据大小
}image; 
#pragma pack()  
//函数
//加载图像 
int image_load(struct image_struct** im, char *path){
	FILE *image_path_fp;
	image_path_fp = fopen(path, "rb");
	if (image_path_fp == NULL){
		return -1;
	}
	//取文件大小
	fseek(image_path_fp, 0, SEEK_END); //定位到文件末 
	int nFileLen = ftell(image_path_fp); //文件长度
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,防止从文件尾读取数据
	//读取头信息
	if (fread((*im), (sizeof(struct image_struct) - ((sizeof(DATA/*image_Data*/)+(sizeof(UINT_32)/*image_Data_Size*/)))/*暂不读取数据,无法从头文件中获取数据偏移量,防止数据混乱*/), 1, image_path_fp) == 0){
		return -2;
	}
	//给data变量分配内存
	(*im)->image_Data = (DATA)malloc(nFileLen-(*im)->image_Offbits/*完整的数据大小*/);
	//判断是否分配成功
	if ((*im)->image_Data == NULL){	//如果没有可用堆内存则malloc返回NULL
		return -3;
	}
	//读取数据
	//读取前将文件指针挪移到文件头信息后,找到正确的数据存储区
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,因为已经fread一次了,所以数据文件指针发生变更
	fseek(image_path_fp, (*im)->image_Offbits, SEEK_CUR);	//忽略头数据
	if (fread((*im)->image_Data, (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/), 1, image_path_fp) == 0){
		return -4;
	}
	//保存文件大小,方便读写操作
	(*im)->image_Data_Size = (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/);
	//文件指针释放,防止占用文件内核的临界资源
	fclose(image_path_fp);
	image_path_fp == NULL;
	return 0;
}
//给图像数据分配内存
int image_malloc(struct image_struct** im){
	*im = (struct image_struct*)malloc(sizeof(struct image_struct));
	if (*im == NULL){
		return -1;
	}
	return 0;
}
//将图像转换成反向图_该方法只能用于真彩图
int image_reverse_rgb(struct image_struct** im){
	if ((*im) == NULL){	//判断传递进来的图像指针是否为空
		return -1;
	}
	//转换成反向图很简单只需要将每个图像里的像素点转换成负的就可以了,注意在一个24位的图像文件中一个字节对应一个颜色值三个字节则为一个完整的像素点,所以我们一个一个像素点的转换就可以了
	//算法公式为:S=-R-G-B
	for (int i = 0; i < (*im)->image_Data_Size; ++i){
			if ((*im)->image_Data[i] == (int)0){	//如果等于0则不处理
				continue;	//开始下一次循环
			}//i*(*im)->image_Width + j
			(*im)->image_Data[i] = -(*im)->image_Data[i];	//调用宏函数转换
	}
	return 0;
}
//保存图像数据到文件
int image_save_file(struct image_struct** im, char *path){
	FILE* file_fp = fopen(path, "wb+");	//以二进制可读写方式打开
	if (file_fp == NULL){	//判断文件指针是否为空
		return -1;
	}
	//写入头信息
	fwrite((*im), (*im)->image_Offbits/*直接写入头文件到数据的偏移量大小即可*/, 1, file_fp);
	//写入文件数据
	fwrite((*im)->image_Data, (*im)->image_Data_Size, 1, file_fp);
	return 0;

}
int main(){
	image *imga;
	image_malloc(&imga);
	image_load(&imga, "test.bmp");
	printf("图像宽度:%d\n", imga->image_Width); 
	printf("图像高度:%d\n", imga->image_Height);
	printf("图像文件占用字节:%d\n", imga->image_Size);
	printf("图像每个像素占用bit位:%d\n", imga->image_Bitcount);
	getchar();
}

运行结果:

本篇先让大家对BMP格式有一个基本的认知,和读取图像头信息中较为重要的信息
2018-03-04 13:24:10 attilax 阅读数 167
  • C++实战OpenCV3.2+QT5播放视频

    OpenCV是目前视频处理的最流行的框架,广泛用于各类项目中,并且由于OpenCV的开源特性可以很容易移植到Android、IOS和嵌入式Linux中,QT5同样是跨平台界面库的第一选择。 本次公开课将基于OpenCV3.2和QT5,详细讲解如下内容: 第一部分将讲解并分析OpenCV的视频处理接口; 第二部分将讲解 QT5如何使用OpenGL高效的绘制图像; 第三部分将讲解如何将OpenCV与QT5结合 通过本次公开课,让学员能对OpenCV的编程和QT5的界面编程 有个总体的认识,为后续继续学习奠定基础。 (1)OpenCV3.2视频接口详解? (2)OpenCV3.2 Mat图像结构详解 (3)QT5自定义Widget (4)QT5基于OpenGL绘制图像 (5)QT5月OpenCV3.2结合播放视频

    1048 人正在学习 去看看 夏曹俊

Atitit 跨平台跨语言图像处理与node.js图像处理之道 attilax

 

1. 著名跨语言类库 ImageMagick简介、GraphicsMagick、命令行 1

1.1. opencv matlab halcon类库的调用 2

2. 常用图像处理 2

2.1. Resize调整大小 缩略图生成 3

2.2. Crop裁剪截切 3

2.3. 识别图片:gm identify   3

2.4. quality 质量:设定jpeg图片输出质量,推荐采用80,此命令仅用于输出格式是jpg的情况,不应省略,省略的话默认质量是95,生成图片过大 +profile "*":图片中不存储Exif信息,必须使用,否则生成图片过大 3

2.5. 旋转图像  rotate 3

2.6. 获取文件信息 Ilibtiff tiffinfo filename.tiff   3

2.7. 二值化 黑百化 convert -monochrome 3

2.8. 添加图片水印处理 3

2.9. 组合合并图像 3

2.10. 格式转换 3

2.11. gif文件中抽取第一帧  3

2.12. 8. 建立gif图像 4

2.13. . 截屏 gm import a.jpg 4

2.14. 反相 convert -negate 4

3. 其他 4

3.1. 遍历像素点 get-pixels 类库 4

4. 参考资料 4

 

 

1. 著名跨语言类库 ImageMagick简介、GraphicsMagick、命令行

1.1. opencv matlab halcon类库的调用

matlab halcon 直接使用cli命令行接口

opencv也有 opencv4nodejs这一类接口模块可用。或者使用python中转cli命令行接口也可

2. 常用图像处理

2.1. Resize调整大小 缩略图生成

2.2. Crop裁剪截切

2.3. 识别图片:gm identify  

2.4. quality 质量:设定jpeg图片输出质量,推荐采用80,此命令仅用于输出格式是jpg的情况,不应省略,省略的话默认质量是95,生成图片过大
+profile "*":图片中不存储Exif信息,必须使用,否则生成图片过大

2.5. 旋转图像  rotate

2.6. 获取文件信息 Ilibtiff tiffinfo filename.tiff  

2.7. 二值化 黑百化 convert -monochrome 

2.8. 添加图片水印处理

2.9. 组合合并图像

2.10. 格式转换

2.11. gif文件中抽取第一帧

gm convert "Image.gif[0]" first.gif
 

2.12. 8. 建立gif图像


gm convert -delay 20 frame*.gif animation.gif
gm convert -loop 50 frame*.gif animation.gif
(让动画循环50次)

2.13. . 截屏 gm import a.jpg

用鼠标点击所要截取的窗口,或者选择截屏区域,保存为a.jpg

 

2.14. 反相 convert -negate  

 

3. 其他

3.1. 遍历像素点 get-pixels 类库

4. 参考资料


ImageMagicK _ 网络进行时.html

ImageMagick简介、GraphicsMagick、命令行使用示例 - CSDN博客.html

2019-12-06 09:31:32 SoaringLee_fighting 阅读数 46
  • C++实战OpenCV3.2+QT5播放视频

    OpenCV是目前视频处理的最流行的框架,广泛用于各类项目中,并且由于OpenCV的开源特性可以很容易移植到Android、IOS和嵌入式Linux中,QT5同样是跨平台界面库的第一选择。 本次公开课将基于OpenCV3.2和QT5,详细讲解如下内容: 第一部分将讲解并分析OpenCV的视频处理接口; 第二部分将讲解 QT5如何使用OpenGL高效的绘制图像; 第三部分将讲解如何将OpenCV与QT5结合 通过本次公开课,让学员能对OpenCV的编程和QT5的界面编程 有个总体的认识,为后续继续学习奠定基础。 (1)OpenCV3.2视频接口详解? (2)OpenCV3.2 Mat图像结构详解 (3)QT5自定义Widget (4)QT5基于OpenGL绘制图像 (5)QT5月OpenCV3.2结合播放视频

    1048 人正在学习 去看看 夏曹俊

DATE: 2019.12.6


https://docs.gimp.org/2.8/zh_CN/

GIMP 是跨平台的图像处理程序。GIMP 是GNU 图像处理程序(GNU Image Manipulation Program)的缩写。GIMP 适用于多种图像处理任务,包括照片润饰、图像合成和创建图像。

GIMP 有许多功能,它既可以作为简单的画图程序,也能作为专家级的照片处理程序,或在线批处理系统、批量图像渲染器,以及图像格式转换工具等。

GIMP 具有可延伸性和可扩展性,它能通过扩展插件 完成各种事情。其高级脚本接口允许用户通过编写简单的脚本完成从最简单到最复杂的各种图像处理过程。

GIMP 特性与功能预览:

  • 完整的图像工具套件,包括画笔、铅笔、喷枪、克隆等工具。

  • 基于平铺(Tile-based)的内存管理使图像大小限制在可用的磁盘空间内。

  • 对所有涂画工具都使用次像素(Sub-pixel)取样,因而能产生高品质的反锯齿效果。

  • 完全地 Alpha 通道支持。

  • 支持图层和通道。

  • 拥有程序化的数据库,可以从外部程序(如 Script-Fu) 调用 GIMP 内部命令。

  • 先进的脚本化处理能力。

  • 多级撤消/重做(只受磁盘空间大小限制)。

  • 变换工具包括旋转,缩放,切变和翻转。

  • 支持包括 GIF、JPEG、PNG、XPM、TIFF、TGA、MPEG、PS、PDF、PCX、BMP 在内的多种文件格式。

  • 选择工具包括矩形、椭圆、自由、模糊、贝赛尔曲线和智能剪刀。

  • 通过插件能让您轻松地添加对新文件格式的支持和效果滤镜。

2018-06-14 21:52:22 chengyq116 阅读数 1063
  • C++实战OpenCV3.2+QT5播放视频

    OpenCV是目前视频处理的最流行的框架,广泛用于各类项目中,并且由于OpenCV的开源特性可以很容易移植到Android、IOS和嵌入式Linux中,QT5同样是跨平台界面库的第一选择。 本次公开课将基于OpenCV3.2和QT5,详细讲解如下内容: 第一部分将讲解并分析OpenCV的视频处理接口; 第二部分将讲解 QT5如何使用OpenGL高效的绘制图像; 第三部分将讲解如何将OpenCV与QT5结合 通过本次公开课,让学员能对OpenCV的编程和QT5的界面编程 有个总体的认识,为后续继续学习奠定基础。 (1)OpenCV3.2视频接口详解? (2)OpenCV3.2 Mat图像结构详解 (3)QT5自定义Widget (4)QT5基于OpenGL绘制图像 (5)QT5月OpenCV3.2结合播放视频

    1048 人正在学习 去看看 夏曹俊

GIMP - GNU 图像处理程序 - 工具栏窗口 (Toolbox) 显示

GIMP 是跨平台的图像处理程序。GIMP 是 GNU 图像处理程序 (GNU Image Manipulation Program) 的缩写。GIMP 适用于多种图像处理任务,包括照片润饰、图像合成和创建图像。
GIMP 有许多功能,它既可以作为简单的画图程序,也能作为专家级的照片处理程序,或在线批处理系统、批量图像渲染器,以及图像格式转换工具等。
GIMP 具有可延伸性和可扩展性,它能通过扩展插件完成各种事情。其高级脚本接口允许用户通过编写简单的脚本完成从最简单到最复杂的各种图像处理过程。
GIMP Image Editor

1. File -> Open


2. GIMP 主面板里,右击弹出菜单 -> Tools -> New Toolbox

 



3. Windows -> Dockable Dialogs -> Tool Options



 
4. 工具选项拖动到工具箱里面


5. Always On Top

 

2016-01-04 15:50:57 lonelyrains 阅读数 2453
  • C++实战OpenCV3.2+QT5播放视频

    OpenCV是目前视频处理的最流行的框架,广泛用于各类项目中,并且由于OpenCV的开源特性可以很容易移植到Android、IOS和嵌入式Linux中,QT5同样是跨平台界面库的第一选择。 本次公开课将基于OpenCV3.2和QT5,详细讲解如下内容: 第一部分将讲解并分析OpenCV的视频处理接口; 第二部分将讲解 QT5如何使用OpenGL高效的绘制图像; 第三部分将讲解如何将OpenCV与QT5结合 通过本次公开课,让学员能对OpenCV的编程和QT5的界面编程 有个总体的认识,为后续继续学习奠定基础。 (1)OpenCV3.2视频接口详解? (2)OpenCV3.2 Mat图像结构详解 (3)QT5自定义Widget (4)QT5基于OpenGL绘制图像 (5)QT5月OpenCV3.2结合播放视频

    1048 人正在学习 去看看 夏曹俊

OpenCV图像处理中的性能测试

本文由 @lonelyrains出品,转载请注明出处。
文章链接: http://blog.csdn.net/lonelyrains/article/details/50456266

opencv中自带跨平台的计时代码实现。源码如下


int64 getTickCount(void)
{
#if defined WIN32 || defined _WIN32 || defined WINCE
    LARGE_INTEGER counter;
    QueryPerformanceCounter( &counter );
    return (int64)counter.QuadPart;
#elif defined __linux || defined __linux__
    struct timespec tp;
    clock_gettime(CLOCK_MONOTONIC, &tp);
    return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
#elif defined __MACH__ && defined __APPLE__
    return (int64)mach_absolute_time();
#else
    struct timeval tv;
    struct timezone tz;
    gettimeofday( &tv, &tz );
    return (int64)tv.tv_sec*1000000 + tv.tv_usec;
#endif
}

double getTickFrequency(void)
{
#if defined WIN32 || defined _WIN32 || defined WINCE
    LARGE_INTEGER freq;
    QueryPerformanceFrequency(&freq);
    return (double)freq.QuadPart;
#elif defined __linux || defined __linux__
    return 1e9;
#elif defined __MACH__ && defined __APPLE__
    static double freq = 0;
    if( freq == 0 )
    {
        mach_timebase_info_data_t sTimebaseInfo;
        mach_timebase_info(&sTimebaseInfo);
        freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
    }
    return freq;
#else
    return 1e6;
#endif
}

其中getTickCount用来计算cpu运算周期数,getTickFrequency用来计算cpu运算频率。总耗时即周期数/频率,单位是秒。

最直观的计时设计:

每次要测一个函数运行性能消耗时,就在运算之前定义一个getTickCount、运算之后定义一个getTickCount,差值/频率,得到消耗时长。

这样做的缺点是,需要每次都重写很多代码。

简单的计时设计:

为了解决每次都重写很多代码的麻烦,可以定义一个全局变量g_tick,然后定义一个宏。每次要更新并打印时,只用调用一次这个宏。
该宏定义可以为:

//一行代码,所以没有续行符‘\’
#define SHOW_TICK() do{printf("%d(ms),func:%s,line:%d\n",int(1000*(cv::getTickCount()-g_tick)/cv::getTickFrequency()),__FUNCTION__,__LINE__); updateTick();}while(0)

这样一来,每次都可以与上一次调用SHOW_TICK()进行比较,得到差值并打印出来。

这样做的缺点是,不是线程安全的。如果从给g_tick加锁的角度考虑问题,则会增加不必要的性能损耗。虽然这点在测试性能的打印中表现不出来,但是会在实际运行中表现出来。

定义一个计时类

检测代码段耗时时,在头和尾每次都分别new一个计时类对象,delete一个对象。构造函数和析构函数中去做计时。

缺点:调用需要写两行代码。

使用之前的调试工具框架

参见专栏给函数增加Debug头
重定义Debug_Func,将计时功能加入到宏中,即可每次运行某一个函数,自动打印计时。

没有更多推荐了,返回首页