【C语言】图像处理-揭秘电影特效,随心所欲,合成图像
20200705@学习C语言第13天
严正声明,这篇文章属于汇编整理型,整理部分属于原创。参考自北京理工大学MOOC公开课,以及百科、博文等资料,已经在相应处附上链接。
图像处理实例
学习C语言最重要的就是要会应用到实践中去,图像处理就是一个非常典型的应用。在别人还在折腾ps蒙板时,你一秒不到就可以实现图片的合成,并且只要稍稍修改代码就可以实现更多样的处理。这到底是怎样做到的呢???来和初学第13天的小学渣一起看看吧。
我们要实现的目的是把这两张图片合成:
图1(图片来源于MOOC北京理工大学公开课)
图2(图片来源于MOOC北京理工大学公开课)
要做这件事情,我们首先了解一下图像文件的特点:
图像文件结构(File structure of images)一般的图像文件结构主要都包含有文件头、文件体和文件尾等三部分。
文件头的主要内容包括产生或编辑该图像文件的软件的信息以及图像本身的参数。这些参数必须完整地描述图像数据的所有特征,因此是图像文件中的关键数据。
文件体主要包括图像数据以及颜色变换查找表或调色板数据。这部分是文件的主体,对文件容量的大小起决定作用。如果是真彩色图像,则无颜色变换查找表或调色板数据,对于256色的调色板,每种颜色值用24 bit表示,则调色板的数据长度为256×3(Byte)。
文件尾可包含一些用户信息。文件尾是可选项,有的文件格式不包括这部分内容。
代码很长,不着急,我们逐条分析:
代码1
// forclass1.cpp : Defines the entry point for the console application.
//
#include "stdio.h"
#include "malloc.h"
#include "memory.h"
#include "math.h"
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef long LONG;
#pragma pack (2)#define PAI 3.1415926typedef struct tagBITMAPFILEHEADER { // bmfhWORD bfType; //TYPE == BM DWORD bfSize; //文件大小 WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits; //图像像素起始位置
} BITMAPFILEHEADER;typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //文件大小 LONG biWidth;LONG biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;LONG biXPelsPerMeter;LONG biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;
} BITMAPINFOHEADER;typedef struct tagRGBQUAD {BYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed;BYTE rgbReserved;
} RGBQUAD;struct BMPStruct
{BITMAPFILEHEADER fileHeader; //文件头 BITMAPINFOHEADER bmphead; //图像头 int lineByte; //图像的实际宽度RGBQUAD *pColorTable; //颜色表指针unsigned char *pBmpBuf; //读入图像数据的指针
};BMPStruct myBMP[3];bool readBmp(char *bmpName, BMPStruct* curBMP)
{FILE *fp=fopen(bmpName,"rb");//二进制读方式打开指定的图像文件if(fp==0) return 0;//跳过位图文件头结构BITMAPFILEHEADERfread(&curBMP->fileHeader, sizeof(BITMAPFILEHEADER), 1,fp); //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中fread(&curBMP->bmphead, sizeof(BITMAPINFOHEADER), 1,fp); //获取图像宽、高、每像素所占位数等信息curBMP->lineByte=(curBMP->bmphead.biWidth * curBMP->bmphead.biBitCount/8+3)/4*4;//灰度图像有颜色表,且颜色表表项为256if(curBMP->bmphead.biBitCount == 8){//申请颜色表所需要的空间,读颜色表进内存curBMP->pColorTable=new RGBQUAD[256];fread(curBMP->pColorTable,sizeof(RGBQUAD),256,fp);}//申请位图数据所需要的空间,读位图数据进内存//curBMP->pBmpBuf=new unsigned char[curBMP->lineByte * curBMP->bmphead.biHeight];curBMP->pBmpBuf = (unsigned char *)malloc(curBMP->lineByte * curBMP->bmphead.biHeight);fread(curBMP->pBmpBuf,1,curBMP->lineByte * curBMP->bmphead.biHeight,fp);fclose(fp);//关闭文件return 1;//读取文件成功
}bool saveBmp(char *bmpName, BMPStruct* curBMP)
{FILE *fp=fopen(bmpName,"wb");//二进制写方式打开指定的图像文件if(fp==0) return 0;//跳过位图文件头结构BITMAPFILEHEADERfwrite(&curBMP->fileHeader, sizeof(BITMAPFILEHEADER), 1,fp); //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中fwrite(&curBMP->bmphead, sizeof(BITMAPINFOHEADER), 1,fp); //获取图像宽、高、每像素所占位数等信息if(curBMP->bmphead.biBitCount == 8){//申请颜色表所需要的空间,读颜色表进内存curBMP->pColorTable=new RGBQUAD[256];fwrite(curBMP->pColorTable,sizeof(RGBQUAD),256,fp);}//申请位图数据所需要的空间,读位图数据进内存fwrite(curBMP->pBmpBuf,1,curBMP->lineByte * curBMP->bmphead.biHeight,fp);fclose(fp);//关闭文件return 1;//读取文件成功
}int compose(BMPStruct mybmp[3])
{if (myBMP[0].bmphead.biHeight < myBMP[1].bmphead.biHeight || myBMP[0].bmphead.biWidth < myBMP[1].bmphead.biWidth){return -1;}unsigned char* pBackground = myBMP[0].pBmpBuf;unsigned char* pForeground = myBMP[1].pBmpBuf;unsigned char* pSave = myBMP[2].pBmpBuf;for(int h = 0 ; h < myBMP[0].bmphead.biHeight; h++){for(int w = 0 ; w < myBMP[0].bmphead.biHeight; w++){if (h < myBMP[1].bmphead.biHeight && w < myBMP[1].bmphead.biWidth){if(! (*(pForeground + w*3 +0) < 100 && *(pForeground + w*3 +1) > 90 && *(pForeground + w*3 +2) < 100) ){*(pSave + w*3 + 0) = *(pForeground + w*3 +0);*(pSave + w*3 + 1) = *(pForeground + w*3 +1);*(pSave + w*3 + 2) = *(pForeground + w*3 +2);}}}pBackground += myBMP[0].lineByte;pForeground += myBMP[1].lineByte;pSave += myBMP[2].lineByte;}}int main()
{readBmp("background.bmp",&myBMP[0]);readBmp("human.bmp",&myBMP[1]);myBMP[2] = myBMP[0];myBMP[2].pBmpBuf = (unsigned char *)malloc(myBMP[2].lineByte * myBMP[2].bmphead.biHeight);memcpy(myBMP[2].pBmpBuf, myBMP[0].pBmpBuf, myBMP[2].lineByte * myBMP[2].bmphead.biHeight);myBMP[2].pColorTable = 0;compose(myBMP);int drawPoint(BMPStruct* mybmp, int y, int x);for(int y = 0; y < myBMP[2].bmphead.biHeight; y ++){for(int x = 0; x < myBMP[2].bmphead.biWidth; x ++){if ( ( x - 540) * (x-540) + (y - 380) * ( y - 380) < 50* 50 ){drawPoint(&myBMP[2],y, x);}}}saveBmp("result.bmp",&myBMP[2]);return 0;
}int drawPoint(BMPStruct* mybmp, int y, int x)
{*(mybmp->pBmpBuf + y * mybmp->lineByte + x*3) = 0;*(mybmp->pBmpBuf + y * mybmp->lineByte + x*3 + 1) = 0;*(mybmp->pBmpBuf + y * mybmp->lineByte + x*3 + 2) = 255;return 0;
}
(代码来源于MOOC北京理工大学公开课)
首先理解图像的概念,图像处理的准备步骤包括采样和量化。
采样顾名思义,就是采取样本。我们图片的样本其实就是像素,是整个图像中不可分割的单位或者是元素。不可分割的意思是它不能够再切割成更小单位抑或是元素,它是以一个单一颜色的小格存在。每一个点阵图像包含了一定量的像素,这些像素决定图像在屏幕上所呈现的大小。
量化是在图像离散化后,将表示图像色彩浓淡的连续变化值离化为整数值的过程。 把量化时所确定的整数值取值个数称为量化级数,也称为颜色深度。
一、预设参数
代码2
#include "stdio.h"
#include "malloc.h"
#include "memory.h"
#include "math.h"
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef long LONG;
#pragma pack (2)
#define PAI 3.1415926
(1)定义类型
首先把需要用到函数的头文件include进来,然后为了方便后面可以用简单明快的语言定义变量类型,先设置DWORD、WORD、BYTE、LONG这几个类型的名称。这里,无符号版本和有符号版本的区别就是无符号类型能保存2倍于有符号类型的正整数数据,为了程序容纳更多的数据量,采用unsigned的形式在相同位数的情况下,所能表达的整数范围变大。
(2)定义偏移方式
这里我们用#pragma pack (2)来让程序中所用到的变量对齐,主要是为了提高程序的效率。
初学C语言的朋友对偏移都不是很熟悉,这里就整理一下自己的理解。想象CPU就像一个小人在边走路边捡硬币,每一步的步长都是一样的,相同的格子最多只能有一个硬币。那么如果硬币是按照每一步一个来摆放,那么相同时间内肯定能够捡到更多硬币。如果一个硬币刚好摆在前半步和后半部中间的位置,那么只有走完两步才能捡起来这个硬币。
于是我们为了提高小人捡硬币的效率,可以改变两个参数,一个是小人每次走的步长,一个是硬币摆放的方式。最有效率的方法一定是让硬币对齐边界,以最少的步数通过一个硬币,为了节约内存可以取硬币长度的最大公约数。
一般地,可以通过下面的方法来改变缺省的对界条件:
· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
另外一种方式:
· __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
· attribute ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
这里有一个栗子,可以对照着理解一下,理解不了也没关系,多看以后就懂了:
代码3
#include <stdio.h>#pragma pack(2)
struct test1
{ //对齐参数 偏移地址 大小 char c1; //1 0 1char c2; //1 1 1short s; //2 2 2int i; //2 4 4
};
#pragma pack()#pragma pack(4)
struct test2
{ //对齐参数 偏移地址 大小char c1; //1 0 1short s; //2 2 2char c2; //1 4 1int i; //4 8 4
};
#pragma pack()#pragma pack(8)
struct S1
{ //对齐参数 偏移地址 大小 short s; //2 0 2long l; //4 4 4
};
struct S2
{ //对齐参数 偏移地址 大小 char c; //1 0 1struct S1 d; //4 4 8 double e;//理论//8 16 8 这里实际是错误的,gcc不支持8字节对齐,所以这里默认是4字节对齐 //实际//4 12 8 所以整个占用内存是20字节
};
#pragma pack()int main()
{printf("sizeof(struct test1) = %d\n",sizeof(struct test1)); //输出8 printf("sizeof(struct test2) = %d\n",sizeof(struct test2)); //输出12printf("sizeof(struct S1) = %d\n",sizeof(struct S1)); //输出8printf("sizeof(struct S2) = %d\n",sizeof(struct S2)); //理论计算应该输出24 但是实际打印输出是20 这是因为gcc不支持8字节内存对齐,所以这里是默认4字节对齐,return 0;
}
————————————————
版权声明:本文为CSDN博主「华哥-2088」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/liuchunjie11/article/details/80502529
二、定义位图文件信息头结构
为了让程序正确识别位图文件,我们按照位图文件的格式定义相关的结构类型。
bfType表示文件类型,是一个正整数变量
bfSize表示文件大小,是一个长正整数变量
bfOffBits表示文件的起始偏移量,是一个长正整数变量。
代码4
typedef struct tagBITMAPFILEHEADER { // bmfhWORD bfType; //TYPE == BM DWORD bfSize; //文件大小 WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits; //图像像素起始位置
} BITMAPFILEHEADER;
二、定义位图信息头结构
然后是定义一个位图信息头结构,包括图片大小biSize,图片宽度biWidth,图片高度biHeight,颜色深度biBitCount颜色深度等信息。
代码5
typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //文件大小 LONG biWidth;LONG biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;LONG biXPelsPerMeter;LONG biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;
} BITMAPINFOHEADER;
三、调色板信息
第三部分是调色板信息。由于我们使用真彩色,这部分可以省略。
代码6
typedef struct tagRGBQUAD {BYTE rgbBlue;BYTE rgbGreen;BYTE rgbRed;BYTE rgbReserved;
} RGBQUAD;
四、像素信息
最后是图像的核心,像素信息。为了保存上面几条所说的信息,我们自定义了一个BMPStruct文件结构类型,通过它来记录数字图片磁盘文件的全部信息。
struct BMPStruct
{BITMAPFILEHEADER fileHeader; //文件头 BITMAPINFOHEADER bmphead; //图像头 int lineByte; //图像的实际宽度RGBQUAD *pColorTable; //颜色表指针unsigned char *pBmpBuf; //读入图像数据的指针
};
五、建立数组
通过BMPStruct结构,生成包含三个元素的结构变量数组。这个数组分别保存前景图像、背景图像以及待合成的图像,待合成的图像初始化为背景图像。
BMPStruct myBMP[3];
准备好以上步骤之后,我们开始读取文件。
六、读取文件
在写主函数之前,我们先定义读与写位图文件的函数。首先是读位图文件:
bool readBmp(char *bmpName, BMPStruct* curBMP)
{FILE *fp=fopen(bmpName,"rb");//二进制只读方式打开指定的图像文件if(fp==0) return 0;//跳过位图文件头结构BITMAPFILEHEADERfread(&curBMP->fileHeader, sizeof(BITMAPFILEHEADER), 1,fp); //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中fread(&curBMP->bmphead, sizeof(BITMAPINFOHEADER), 1,fp); //获取图像宽、高、每像素所占位数等信息curBMP->lineByte=(curBMP->bmphead.biWidth * curBMP->bmphead.biBitCount/8+3)/4*4;//灰度图像有颜色表,且颜色表表项为256if(curBMP->bmphead.biBitCount == 8){//申请颜色表所需要的空间,读颜色表进内存curBMP->pColorTable=new RGBQUAD[256];fread(curBMP->pColorTable,sizeof(RGBQUAD),256,fp);}//申请位图数据所需要的空间,读位图数据进内存//curBMP->pBmpBuf=new unsigned char[curBMP->lineByte * curBMP->bmphead.biHeight];curBMP->pBmpBuf = (unsigned char *)malloc(curBMP->lineByte * curBMP->bmphead.biHeight);fread(curBMP->pBmpBuf,1,curBMP->lineByte * curBMP->bmphead.biHeight,fp);fclose(fp);//关闭文件return 1;//读取文件成功
}
FILE *fp=fopen(bmpName,“rb”);
定义一个布尔(bool)类型的函数readBmp,然后以二进制只读方式打开名称为bmpname的图片文件,指针位于文件开头。
if(fp==0) return 0;
避免出现错误。
fread(&curBMP->fileHeader, sizeof(BITMAPFILEHEADER), 1,fp);
首先读取一个文件头大小的数据块,存放于BMPStruct结构变量的文件头成员中。
fread(&curBMP->bmphead, sizeof(BITMAPINFOHEADER), 1,fp);
类似地,读取一个图像头大小的数据块,存放于BMPStruct结构变量的图像头成员中。
如果图像为真彩色,则跳过下一个结构的读取,直接进入像素的读取。
在读取像素值之前,我们需要开辟一个相应的存储空间。
curBMP->pBmpBuf = (unsigned char *)malloc(curBMP->lineByte * curBMP->bmphead.biHeight);
使用malloc函数开辟由图像的实际宽度lineByte,乘以图像高度bmphead.biHeight所得到大小的空间,并定义为字符类型。BMPStruct结构中的curBMP指向这个空间。
fread(curBMP->pBmpBuf,1,curBMP->lineByte * curBMP->bmphead.biHeight,fp);
将图片中所有的像素数据存入刚刚定义的空间,以1为步长,存储像素数量次。
这样就完成了像素的读取。
七、写文件
写位图文件的函数的语法与读文件是一摸一样的:
bool saveBmp(char *bmpName, BMPStruct* curBMP)
{FILE *fp=fopen(bmpName,"wb");//二进制写方式打开指定的图像文件if(fp==0) return 0;//跳过位图文件头结构BITMAPFILEHEADERfwrite(&curBMP->fileHeader, sizeof(BITMAPFILEHEADER), 1,fp); //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中fwrite(&curBMP->bmphead, sizeof(BITMAPINFOHEADER), 1,fp); //获取图像宽、高、每像素所占位数等信息if(curBMP->bmphead.biBitCount == 8){//申请颜色表所需要的空间,读颜色表进内存curBMP->pColorTable=new RGBQUAD[256];fwrite(curBMP->pColorTable,sizeof(RGBQUAD),256,fp);}//申请位图数据所需要的空间,读位图数据进内存fwrite(curBMP->pBmpBuf,1,curBMP->lineByte * curBMP->bmphead.biHeight,fp);fclose(fp);//关闭文件return 1;//读取文件成功
}
八、图片合成函数
现在定义合成图片的函数
int compose(BMPStruct myBMP[3])
{if (myBMP[0].bmphead.biHeight < myBMP[1].bmphead.biHeight || myBMP[0].bmphead.biWidth < myBMP[1].bmphead.biWidth){return -1;}unsigned char* pBackground = myBMP[0].pBmpBuf;unsigned char* pForeground = myBMP[1].pBmpBuf;unsigned char* pSave = myBMP[2].pBmpBuf;for(int h = 0 ; h < myBMP[0].bmphead.biHeight; h++){for(int w = 0 ; w < myBMP[0].bmphead.biHeight; w++){if (h < myBMP[1].bmphead.biHeight && w < myBMP[1].bmphead.biWidth){if(! (*(pForeground + w*3 +0) < 100 && *(pForeground + w*3 +1) > 90 && *(pForeground + w*3 +2) < 100) ){*(pSave + w*3 + 0) = *(pForeground + w*3 +0);*(pSave + w*3 + 1) = *(pForeground + w*3 +1);*(pSave + w*3 + 2) = *(pForeground + w*3 +2);}}}pBackground += myBMP[0].lineByte;pForeground += myBMP[1].lineByte;pSave += myBMP[2].lineByte;}
}
首先输入刚才所生成的my
刚刚说过myBMP使用来存放图像的前景,背景,以及待合成的图像。当前景的高度或者宽度大于背景时,返回-1。
if (myBMP[0].bmphead.biHeight < myBMP[1].bmphead.biHeight || myBMP[0].bmphead.biWidth < myBMP[1].bmphead.biWidth){return -1;}
所以
unsigned char* pBackground = myBMP[0].pBmpBuf;unsigned char* pForeground = myBMP[1].pBmpBuf;unsigned char* pSave = myBMP[2].pBmpBuf;
然后通过先行后列的方式,依次遍历所有像素的坐标。然后判断当前的前景图像是否为绿色的,如果满足则判断为前景,于是将前景值赋值于合成图像。这样我们就完成了图像的合成工作。
for(int h = 0 ; h < myBMP[0].bmphead.biHeight; h++){for(int w = 0 ; w < myBMP[0].bmphead.biHeight; w++){if (h < myBMP[1].bmphead.biHeight && w < myBMP[1].bmphead.biWidth){if(! (*(pForeground + w*3 +0) < 100 && *(pForeground + w*3 +1) > 90 && *(pForeground + w*3 +2) < 100) ){*(pSave + w*3 + 0) = *(pForeground + w*3 +0);*(pSave + w*3 + 1) = *(pForeground + w*3 +1);*(pSave + w*3 + 2) = *(pForeground + w*3 +2);}}}pBackground += myBMP[0].lineByte;pForeground += myBMP[1].lineByte;pSave += myBMP[2].lineByte;}
九、主程序
最后的最后,来到主程序
int main()
{readBmp("background.bmp",&myBMP[0]);readBmp("human.bmp",&myBMP[1]);myBMP[2] = myBMP[0];myBMP[2].pBmpBuf = (unsigned char *)malloc(myBMP[2].lineByte * myBMP[2].bmphead.biHeight);memcpy(myBMP[2].pBmpBuf, myBMP[0].pBmpBuf, myBMP[2].lineByte * myBMP[2].bmphead.biHeight);myBMP[2].pColorTable = 0;compose(myBMP);int drawPoint(BMPStruct* mybmp, int y, int x);for(int y = 0; y < myBMP[2].bmphead.biHeight; y ++){for(int x = 0; x < myBMP[2].bmphead.biWidth; x ++){if ( ( x - 540) * (x-540) + (y - 380) * ( y - 380) < 50* 50 ){drawPoint(&myBMP[2],y, x);}}}saveBmp("result.bmp",&myBMP[2]);return 0;
}
首先分别读取背景图像与前景图像,并将背景图像赋值给将要合成的第三个图像变量,然后将这三个图像变量输入到合成函数中进行合成。最后就可以得到我们最终的结果。
一点困惑求解答
和大家说明一下,本人也是刚学13天的新人,说错的地方请大佬们原谅。然后这个程序在最新版的devc++上应该运行会出错,显示char型的值不能赋值给char*型的变量:
对于这个问题我尝试了以下把readBmp和writeBmp中的char改成const char,这样的确可以编译了,但是。
出来的图是无法打开的。
各位大佬,有偿求搞定这个功能hhh,虽然运行不了但我认为是有意义的,至少看懂这些代码了。再接再厉,先再学一下面向对象,别人的程序抄过来能用是第一步。
【C语言】图像处理-揭秘电影特效,随心所欲,合成图像相关推荐
- 通过python和两张图片实现漫天蝴蝶飞舞的合成图像
学校里的老师要求用python语言实现漫天蝴蝶飞舞的合成图像,在网上找不到这道题,找到类似的也是用matlab写的. 然后自己写完之后觉得展示的效果还不错,就分享出来让有需要的同学来参考参考. 原题如 ...
- The Foundry NUKE 12 mac版(电影特效合成制作软件)
The Foundry NUKE 12 mac版是电影特效合成制作软件,NUKE能为艺术家提供组合和操作扫描的照片,视频板以及计算机生成的图像的灵活.有效.节约和全功能的工具. NUKE 12 Mac ...
- c语言给bmp图片加滤镜,图片编辑器PixelStyle: 图像处理,滤镜特效
图片编辑器PixelStyle: 图像处理,滤镜特效 支持系统 OS X 10.8 价格 0 下载次数 590 官方网站 *不要错过"超级抠图",一键抠图工具,从此告别PS的蜗牛抠 ...
- 陈启峰:人工智能生成图像技术,未来或能取代电影特效
2019年1月21日,<麻省理工科技评论>公布了2018年"35岁以下创新35人"(Innovators Under 35 China)中国区榜单.从榜单中,我们看到更 ...
- 电影特效用到什么计算机知识,后期影视特效处理知识普及
电影特效作为电影产业中不可或缺的元素之一,为电影的发展做出了巨大的贡献.今天小编主要给大家分享后期影视特效处理知识普及,希望对你们有帮助! 影视特效改变电影制作的方式 在目前的电影制作过程中,从分镜头 ...
- 计算机在电影中的应用,谈计算机动画在电影特效中的应用
[摘要] 计算机动画是采用图形与图像处理技术,借助于编程或动画制作软件生成一系列的景物画面.计算机动画的一个重要应用就是制作电影特效.计算机动画在虚拟场景的创建.动力仿真及后期合成等特效中有着重要的作 ...
- 世界著名电影特效公司
工业光魔 Industrial Light and Magic 创 始 人:乔什·卢卡斯 创立时间:1981 核心技术:CGI动画技术,模型拍摄,全数字高清晰设想技术:凭<星球大战> ...
- 文本合成图像栩栩如生,仿佛拥有人类的语言想象力:OpenAI祭出120亿参数魔法模型!...
点击上方"机器学习与生成对抗网络",关注"星标" 获取有趣.好玩的前沿干货! 作者 | OpenAI 来源 | AI科技评论 编译 | 贝爽.陈大鑫 前几个月G ...
- OpenAI祭出120亿参数魔法模型!从文本合成图像栩栩如生,仿佛拥有人类的语言想象力...
来源:AI科技评论 作者:OpenAI 编译:贝爽.陈大鑫 前几个月GPT-3刚刚问世的时候,能够根据一段话就写出一个小说.一段哲学语录,就足以令AI圈为之感到兴奋. 然而2020年刚刚开始没多久,O ...
最新文章
- centos pureftpd mysql_使用PureFTPd和MySQL的虚拟主机(包括配额和带宽管理)在CentOS 6.2上...
- 来自于参赛队伍所反映的总决赛落选之后的建议
- java 扩展类加载器_java实现自定义类加载器
- Uber无人车撞死人,安全员被控过失杀人,算法免于追责
- [小结]硬盘分区的知识与意义
- 2022年跨境品牌出海新玩法策略:Tiktok+速卖通平台运营必不可少
- mysql 删除外键
- linux安装mysql后怎么进去_linux安装mysql详细步骤
- google浏览器不能登录
- Ubuntu18.04安装cmake(附免费下载cmake)。
- m1电脑推荐使用Google Chrome浏览器
- css图片插入文字,利用css布局在图片插入文字
- 儿童讲堂 - 量词举例
- 树莓派安装MPlayer播放器
- Axi协议和verilog实现1-AXI总线和关键问题描述
- JVM系列(十三)——垃圾回收器
- php做网站需要注意什么,浅谈新手做网站应该注意的问题
- week-15(ZJM 与霍格沃兹)
- 计算机类学生考试系统,学生在线考试系统.doc
- DynamicDto链式实现动态数据传输对象