一、实验目的
掌握基于算能平台的JPEG压缩编码方法以及开发环境,包括开发主机环境搭建,硬件嵌入式开发板的连接,云平台的配置,编码程序的编译、运行等。
二、实验内容
搭建实验开发环境,并编写静止图像jpeg格式编解码程序,输入端读取原始图像数据,选择编解码模式,输出压缩编码结果。在目标开发机运行测试,验证开发环境。如果是基于云平台虚拟环境,则需要将编译好的程序代码上传云平台进行测试运行。
三、开发环境
开发主机:Ubuntu 20.04.6 LTS
硬件:算能SE5
四、实验器材
开发主机 + 云平台(或SE5硬件)
五、实验过程与结论
实验原理概述
本小节重点讨论JPEG编解码实验。JPEG是当前流行的静态图像压缩格式,从创造至今已经过去几十年,但依然是当今互联网时代的主要图像压缩标准。原始未压缩的图片,经过压缩算法运行后,生成jpeg格式的压缩图片。其占用的对于原始图像数据空间更小,更有利于图像文件的存储和传输。PEG编码包括预测编码、变换编码、量化、熵编码等过程,在之前的理论课程中已经充分学习并熟练掌握其基本原理。本实验的JPEG编解码实现代码通过直接调用OpenCV库实现。
算能的OpenCV库提供了imencode和imdecode分别进行编码和解码。和OpenCV的其他函数使用方法一样,imencode和imdecode同样针对Mat数据进行处理。在imencode函数中读取Mat数据格式图片进行编码,在imdecode将解码后的数据通过Mat数据格式返回。
编解码实验过程
JPEG编码:
本实验可以封装FnEncode函数用于进行编码,函数关键代码如下:
void FnEncode(const char *filenpath, int output_en)
{
Mat save = imread(filenpath, IMREAD_UNCHANGED);
vector<uint8_t> encoded;
imencode(".jpg", save, encoded); //编码
if (output_en)
{
char *str = "encodeImage.jpg";
int bufLen = encoded.size();
if (bufLen)
{
uint8_t *pYuvBuf = encoded.data();
FILE *fclr = fopen(str, "wb");
fwrite(pYuvBuf, 1, bufLen, fclr); //编码后的数据写入文件
fclose(fclr);
}
}
}
JPEG解码:
本实验可以封装FnDecode函数用于进行编码,函数关键代码如下:
void FnDecode(const char *filenpath, int output_en)
{
ifstream in(filenpath, ios::binary);
string s((istreambuf_iterator<char>(in)), (istreambuf_iterator<char>()));
in.close();
vector<char> pic(s.c_str(), s.c_str() + s.length());
Mat image;
imdecode(pic, IMREAD_UNCHANGED, &image); //解码
if (output_en)
{
char *str = "decodeImage.bmp";
imwrite(str, image); //解码后写入文件
}
}
主函数:
最后我们通过封装主函数,分别对输入的图片进行编码或解码:
int main(int argc, char *argv[])
{
.....
switch (codec_type)
{
case 1:
/* code */
FnEncode(input_file.data(), outputEnable);
cout << "encode finish ." << endl;
break;
case 2:
FnDecode(input_file.data(), outputEnable);
cout << "decode finish ." << endl;
break;
default:
cout << "please input correct codec type number." << endl
<< " "
<< " [codec-type] - the codec type you want to use . 1 -> encode ,2 -> decode" << endl;
break;
}
}
如上所示,我们可以在主函数中根据用户输入不同的codec_type即编码或者解码,分别对输入的图片进行编码和解码。outputEnable是由用户指定是否输出到文件。
执行与测试
本地编译后上传到云平台或者本地SE5盒子中的过程与前面的方法相同,这里不再赘述。上传完成后,在终端中输入指令:
root@d11ae417e206:/tmp/test# ./jpeg_EncDec lena.bmp 1 1
各个指令的解释如下表所示:
指令:./test_ocv_jpumulti <inputfile> <test type> <isOut>
参数说明:
- inputfile: 输入图像文件
- test type: 选择测试功能, 1: 编码, 2: 解码,
- IsOut: 是否输出到文件, 0: 不生成输出文件, 1: 生成输出文件
编码输出结果如下:
root@211bf635cafb:/tmp/test# ./test_ocv_jpumulti lena.bmp 1 1
输入文件的路径:lena.bmp
编解码类型:11-编码2-解码
Open /dev/jpu successfully, device index = e, jpu fd = 6,vpp fd = 7编码完成
root@211bf635cafb:/tmp/test# ./test_ocv_jpumulti EncodeImage.jpg 2 1输入文件的路径:EncodeImage.jpg
编解码类型:21-编码2-解码
Open /dev/jpu successfully, device index = e, jpu fd= 4, vpp fd = 5解码完成
结果分析:根据指令我们选择编解码模式1,也就是编码,输入为图片:lena.bmp,选择输出到图片(isOut=1)。结果显示,65KB的图片压缩成了15KB;另外,我们再运行一次程序,选择编解码模式2,也就是解码,输入刚才编码输出的图片EnCodeImage.jpg,进行解码,同样也选择解码文件输出输出到图片(isOut=1)。结果显示,15KB的压缩图片还原成了65KB,并得到了指定的原来的格式的图片DecodeImage.bmp。
信息如下图所示。