有一段时间没写东西了,以前写了篇文章《一个神奇的无损压缩实验来撼动“信息论”!!!最终结果无法想象》,这个实验的出来后也一直没有花心思和时间进行详细的测试,近来写了一套程序做了一个详细的测试,尽管后续还要更多的研究,但是我觉得从本次的实验来看,前文中描述到的滤波从实验上是有表现的,感兴趣的朋友或学者可以联系我([email protected])。本文也算是对2021年研究工作的一个总结。废话不多说了,先来看我的实验。
测试图样:Lena.bmp
由于博客里面不能上传BMP图像,这里只是用了一个jpg图贴上来了。另外,针对BMP文件的读写程序和控制台main程序如下:
#include "bmp.h" #include#include #include #include #ifdef WIN32 #define inline __inline #endif // WIN32 const char* fileName1 = "D:\WJLCoding\理论研究备份\C++程序\开发中版本\WJLImageCodeByEntropyTransformation1.0.0\TestImage\Lena.bmp";// Lena512.bmp const char* fileName3 = "D:\WJLCoding\理论研究备份\C++程序\开发中版本\WJLImageCodeByEntropyTransformation1.0.0\NewImage\Lena-444.bmp"; // 方便统计字节中各个1的数量 unsigned char CntOfOneSymboltemp[256]= { 0x00,0x01,0x01,0x02,0x01,0x02,0x02,0x03,0x01,0x02,0x02,0x03,0x02,0x03,0x03,0x04, 0x01,0x02,0x02,0x03,0x02,0x03,0x03,0x04,0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05, 0x01,0x02,0x02,0x03,0x02,0x03,0x03,0x04,0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05, 0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05,0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06, 0x01,0x02,0x02,0x03,0x02,0x03,0x03,0x04,0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05, 0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05,0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06, 0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05,0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06, 0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06,0x04,0x05,0x05,0x06,0x05,0x06,0x06,0x07, 0x01,0x02,0x02,0x03,0x02,0x03,0x03,0x04,0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05, 0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05,0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06, 0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05,0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06, 0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06,0x04,0x05,0x05,0x06,0x05,0x06,0x06,0x07, 0x02,0x03,0x03,0x04,0x03,0x04,0x04,0x05,0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06, 0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06,0x04,0x05,0x05,0x06,0x05,0x06,0x06,0x07, 0x03,0x04,0x04,0x05,0x04,0x05,0x05,0x06,0x04,0x05,0x05,0x06,0x05,0x06,0x06,0x07, 0x04,0x05,0x05,0x06,0x05,0x06,0x06,0x07,0x05,0x06,0x06,0x07,0x06,0x07,0x07,0x08 }; // 下面是测试图像压缩的算法,必须是BMP压缩成jlm格式 int main(){ long t1,t2; long cont1 = 0, i =0; BmpImage* inimg; int flag; //---------------------------------------------------------------------------------------------------------------------------------------- // BMP编码部分 inimg = LoadBmpImage(fileName1); // 统计R分量中的符号1概率 for(i = 0; i < inimg->height*inimg->width; ++i) { cont1 += CntOfOneSymboltemp[inimg->rgbData->ucR[i]]; } for(i = 0; i < inimg->height*inimg->width; ++i) { cont1 += CntOfOneSymboltemp[inimg->rgbData->ucG[i]]; } for(i = 0; i < inimg->height*inimg->width; ++i) { cont1 += CntOfOneSymboltemp[inimg->rgbData->ucB[i]]; } printf("n降熵编码结果中符号1的概率:%fn",(double)cont1/ (inimg->height*inimg->width * 3.0 * 8.0)); //---------------------------------------------------------------------------------------------------------------------------------------- flag = SaveBmpImage(fileName3, inimg); if(flag == 1){ printf("save ok...n"); }else{ printf("save failure...n"); } system("pause"); return 0; }
然后是BMP文件的读写程序:
#include "bmp.h" #include "WJLEntropyTransformation.h" // 装载BMP图像信息,需要注意目前装载图像的最大值是有限的,只能压缩RGB24位真彩色 BmpImage* LoadBmpImage(const char* path) { BmpImage* bmpImg; FILE* pFile; double ProbabilityofOne = 人为设定0.5-0.9之间的值; unsigned short fileType; BitMapFileHeader bmpFileHeader; BitMapInfoHeader bmpInfoHeader; int channels = 1; int width = 0; int height = 0; int step = 0; int offset = 0; unsigned char pixVal; unsigned char *ucRtmp, *ucGtmp, *ucBtmp; unsigned int ucRlenght; int i, j, k, index; bmpImg = (BmpImage*)malloc(sizeof(BmpImage)); bmpImg->rgbData = (RGB*)malloc(sizeof(RGB)); pFile = fopen(path, "rb"); if (!pFile) { free(bmpImg); return NULL; } fread(&fileType, sizeof(unsigned short), 1, pFile); if (fileType == 0x4D42) { fread(&bmpFileHeader, sizeof(BitMapFileHeader), 1, pFile); fread(&bmpInfoHeader, sizeof(BitMapInfoHeader), 1, pFile); if (bmpInfoHeader.biBitCount == 24) { channels = 3; index = 0; width = bmpInfoHeader.biWidth; height = bmpInfoHeader.biHeight; bmpImg->width = width; bmpImg->height = height; bmpImg->channels = 3; // 三通道 bmpImg->rgbData->ucR = (unsigned char*)malloc(sizeof(unsigned char) * width * height); bmpImg->rgbData->ucG = (unsigned char*)malloc(sizeof(unsigned char) * width * height); bmpImg->rgbData->ucB = (unsigned char*)malloc(sizeof(unsigned char) * width * height); step = channels * width; offset = (channels * width) % 4; if (offset != 0) { offset = 4 - offset; } for (i=0; irgbData->ucR[index] = pixVal; }else if(k == 1){ bmpImg->rgbData->ucG[index] = pixVal; }else if(k == 2){ bmpImg->rgbData->ucB[index] = pixVal; index ++; } } } if (offset != 0) { for (j=0; j yuvData = RGB2YUV(quad, width, height, MODE444, 1); ucRtmp = (unsigned char*)malloc(sizeof(unsigned char) * width * height); ucGtmp = (unsigned char*)malloc(sizeof(unsigned char) * width * height); ucBtmp = (unsigned char*)malloc(sizeof(unsigned char) * width * height); ucRlenght = width * height; // 对RGB进行降熵 WJLLosslessDropEntropyCoding(bmpImg->rgbData->ucR, width * height, ucRtmp, &ucRlenght, &ProbabilityofOne); WJLLosslessDropEntropyCoding(bmpImg->rgbData->ucG, width * height, ucGtmp, &ucRlenght, &ProbabilityofOne); WJLLosslessDropEntropyCoding(bmpImg->rgbData->ucB, width * height, ucBtmp, &ucRlenght, &ProbabilityofOne); // 将ucRtmp复制到bmpImg->rgbData->ucR中 memcpy(bmpImg->rgbData->ucR, ucRtmp, width * height); memcpy(bmpImg->rgbData->ucG, ucGtmp, width * height); memcpy(bmpImg->rgbData->ucB, ucBtmp, width * height); free(ucRtmp); free(ucGtmp); free(ucBtmp); // 释放资源 //free(quad->ucR); //free(quad->ucG); //free(quad->ucB); //free(quad); } } fclose(pFile); return bmpImg; } // 测试通过 int SaveBmpImage(const char* path, BmpImage* bmpImg) { FILE *pFile; unsigned short fileType; BitMapFileHeader bmpFileHeader; BitMapInfoHeader bmpInfoHeader; double ProbabilityofOne = 人为设定0.5-0.9之间的值,与LoadBmpImage函数一致; int step; int offset; unsigned char pixVal = ''; int i, j, index; //RGB* quad; unsigned char *ucRtmp, *ucGtmp, *ucBtmp; unsigned int ucRlenght; pFile = fopen(path, "wb"); if (!pFile) { return 0; } fileType = 0x4D42; fwrite(&fileType, sizeof(unsigned short), 1, pFile); if (bmpImg->channels == 3)//24位,三通道,彩图 { step = bmpImg->channels*bmpImg->width; offset = step % 4; if (offset != 4) { step += 4 - offset; } bmpFileHeader.bfSize = bmpImg->height * step + 54; bmpFileHeader.bfReserved1 = 0; bmpFileHeader.bfReserved2 = 0; bmpFileHeader.bfOffBits = 54; fwrite(&bmpFileHeader, sizeof(BitMapFileHeader), 1, pFile); bmpInfoHeader.biSize = 40; bmpInfoHeader.biWidth = bmpImg->width; bmpInfoHeader.biHeight = bmpImg->height; bmpInfoHeader.biPlanes = 1; bmpInfoHeader.biBitCount = 24; bmpInfoHeader.biCompression = 0; bmpInfoHeader.biSizeImage = bmpImg->height * step; bmpInfoHeader.biXPelsPerMeter = 0; bmpInfoHeader.biYPelsPerMeter = 0; bmpInfoHeader.biClrUsed = 0; bmpInfoHeader.biClrimportant = 0; fwrite(&bmpInfoHeader, sizeof(BitMapInfoHeader), 1, pFile); index = 0; // 将YUV转变成为RGB //quad = YUV2RGB(bmpImg->yuvData, bmpImg->width, bmpImg->height, MODE444, 1); ucRtmp = (unsigned char*)malloc(sizeof(unsigned char) * bmpImg->height * bmpImg->width); ucGtmp = (unsigned char*)malloc(sizeof(unsigned char) * bmpImg->height * bmpImg->width); ucBtmp = (unsigned char*)malloc(sizeof(unsigned char) * bmpImg->height * bmpImg->width); ucRlenght = bmpImg->height * bmpImg->width; // 对RGB进行升熵 WJLLosslessIncreaseEntropyCoding(bmpImg->rgbData->ucR, bmpImg->height * bmpImg->width, ucRtmp, &ucRlenght, &ProbabilityofOne); WJLLosslessIncreaseEntropyCoding(bmpImg->rgbData->ucG, bmpImg->height * bmpImg->width, ucGtmp, &ucRlenght, &ProbabilityofOne); WJLLosslessIncreaseEntropyCoding(bmpImg->rgbData->ucB, bmpImg->height * bmpImg->width, ucBtmp, &ucRlenght, &ProbabilityofOne); // 将ucRtmp复制到bmpImg->rgbData->ucR中 memcpy(bmpImg->rgbData->ucR, ucRtmp, bmpImg->height * bmpImg->width); memcpy(bmpImg->rgbData->ucG, ucGtmp, bmpImg->height * bmpImg->width); memcpy(bmpImg->rgbData->ucB, ucBtmp, bmpImg->height * bmpImg->width); free(ucRtmp); free(ucGtmp); free(ucBtmp); for (i = bmpImg->height-1; i > -1; i--) { for (j = 0; j < bmpImg->width; j++) { pixVal = bmpImg->rgbData->ucR[index]; fwrite(&pixVal, sizeof(unsigned char), 1, pFile); pixVal = bmpImg->rgbData->ucG[index]; fwrite(&pixVal, sizeof(unsigned char), 1, pFile); pixVal = bmpImg->rgbData->ucB[index]; fwrite(&pixVal, sizeof(unsigned char), 1, pFile); index ++; } if ( offset != 0 ) { for ( j = 0; j < 4 - offset; j++) { pixVal = 0; fwrite(&pixVal, sizeof(unsigned char), 1, pFile); } } } } fclose(pFile); return 1; }
我写的降熵和升熵程序涉及技术保密以及发明专利,请遵守开源原则,我欢迎大家一起研究,暂时不公开,但可以联系我本人获取。头文件如下:
#ifndef _WJLEntropyTransformation_h #define _WJLEntropyTransformation_h #include "stdlib.h" #include "math.h" void WJLLosslessIncreaseEntropyCoding(unsigned char *InByteArray, unsigned int InByteArray_length, unsigned char *OutByteArray, unsigned int *OutByteArray_length, double *ProbabilityofOne); void WJLLosslessDropEntropyCoding(unsigned char *InByteArray, unsigned int InByteArray_length, unsigned char *OutByteArray, unsigned int *OutByteArray_length, double *ProbabilityofOne); #endif
实验过程为,人为设定ProbabilityofOne的值,0.5到0.9之间,降熵后统计符号1的概率,然后再升熵保存为BMP的图像
实验一:ProbabilityofOne=0.5
控制台运行结果为:
升熵后的BMP保存位置为:
将其保存为Jpg:
这个过程是无损的。
升熵后的图(只能上传jpg格式,所以转成了jpg):
(1)本实验既没有用YUV的转换,也没有采用任何的处理过程,所有的图像直接反应了实验真实结果。图像中的亮点,不用说也知道一定是255的值,所以才会使得符号1的统计概率达到0.9以上了。
(2)图像上部存在黑色块的问题,这个只要变换时适当的拓延即可,学过小波变换的估计也知道小波变换也需要适当的拓延。
或许有人会问,怎么证明比DCT或小波变换好?说实在的,我这么多年的独立研究重点是算法的数学模型,也是自己的兴趣。对于延伸的研究精力和资金也有限,发明一款新的效率高、完全自主的图像视频压缩算法也不是不可能,行业壁垒高,标准化也难,而大部分人员并没有研究欲望只会拿来主义,我也没必要向其公开全部的源码。反正一句话,感兴趣的自然感兴趣,像极化码一样,一篇论文就有人砸钱,哈哈!!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)