
有一段时间没写东西了,以前写了篇文章《一个神奇的无损压缩实验来撼动“信息论”!!!最终结果无法想象》,这个实验的出来后也一直没有花心思和时间进行详细的测试,近来写了一套程序做了一个详细的测试,尽管后续还要更多的研究,但是我觉得从本次的实验来看,前文中描述到的滤波从实验上是有表现的,感兴趣的朋友或学者可以联系我(254908447@qq.com)。本文也算是对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; jyuvData = 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条)