索引合并压缩算法的思路是:
索引合并压缩算法有一种有损压缩,主要用于对包含一定噪音的整型数组进行合并压缩。算法原理就像下雨一样,每一滴都会溅射出一小片湿润区域,如果下一滴落在前面的湿润区域那么 就加强该区域,并且重新计算湿润中心;如果两片区域重叠 那么就将两片合并,并且重新计算湿润中心。
算法描述:
前段时间研究红外遥控器学习模型,由于学习过程中采集到的红外码是一个整型数组且在数值上很不规范,有可能是噪声的原因,获得的整型数组会有很微小的波动偏差,使得垃圾数据含量很大。导致红外码存储,传输,分析都十分困难。雨滴算法,就是把数值上十分接近的码值合并成一个,并用所有修正后的码值建立索引表,之后把所有码值使用索引表的下标表示,经过分析观察,发现所有经过索引的码值均在16的范围之内,于是进一步把该值压缩到半个字节了也就是半个byte或者char内,然后把索引表附到变形后的数组之前,共同组成加密后的红外码。经过这些校正和压缩,新的码值数组长度为以前数据长度的八分之一加上索引表的长度。
java算法如下:
import java.util.LinkedList;
import java.util.List;
public class XiaoMiAlgRainEncode2 {
static final short ALG_RAIN_MAGIC =(short) 0xA567;
static final int WET_NUM =16;
static final int SAMPLE_NUM= 1000;
static final int SOAK_RANGE = 26; //39//80
public class AlgRain {
public int avr;
public int total;
public int min;
public int max;
public int cnt;
public short idx;
public AlgRain(int val, int min, int max) {
super();
this.avr = val;
this.total = val;
this.min = min;
this.max = max;
this.cnt = 1;
}
public AlgRain() {
super();
this.avr = 0;
this.total = 0;
this.min = 0;
this.max = 0;
this.cnt = 0;
}
@Override
public String toString() {
return "AlgRain [avr=" + avr + ", total=" + total + ", min=" + min
+ ", max=" + max + ", cnt=" + cnt + ", idx=" + idx + "]";
}
}
public class AlgRainTable {
public short m_ver = 0;
public short num = 0;
public int[] val= new int[WET_NUM];
public AlgRainTable() {
super();
this.m_ver = ALG_RAIN_MAGIC;
this.num = 0;
//System.arraycopy(val, 0, 0x00, 0, 1);
for (int i = 0; i < WET_NUM; i++)
{
val[i] = 0;
}
}
}
private List<AlgRain> mWets = new LinkedList<AlgRain>();
private AlgRainTable mArt = new AlgRainTable();
private static boolean isCross(AlgRain w, AlgRain ref)
{
return (Math.max(w.min, ref.min) <= Math.min(w.max, ref.max));
}
private void soak()
{
for (int i = 0; i < mWets.size(); i++)
{
AlgRain w1 = mWets.get(i);
for (int j = i+1; j < mWets.size(); j++)
{
AlgRain w2 = mWets.get(j);
if (isCross(w1, w2))
{
(mWets.get(i)).total += w2.total;
(mWets.get(i)).cnt += w2.cnt;
(mWets.get(i)).avr = (mWets.get(i)).total/(mWets.get(i)).cnt;
(mWets.get(i)).max = Math.max((mWets.get(i)).max, w2.max);
(mWets.get(i)).min = Math.max((mWets.get(i)).min, w2.min);
mWets.remove(j);
}
}
}
}
private void alg_rain_reset()
{
mWets.clear();
}
private int alg_rain_feed(int sample)
{
AlgRain w = new AlgRain(sample, sample - SOAK_RANGE/2, sample + SOAK_RANGE/2);
for (AlgRain ww: mWets)
{
if (isCross(ww, w))
{
ww.total += w.total;
ww.cnt += w.cnt;
ww.avr = ww.total/ww.cnt;
ww.max = Math.max(ww.max, w.max);
ww.min = Math.max(ww.min, w.min);
return 0;
}
}
mWets.add(w);
//soak();
return 0;
}
private int alg_rain_feed_finish()
{
short idx = 0;
int cnt = 0;
soak();
for (AlgRain w: mWets)
{
w.idx = idx;
mArt.val[idx] = w.avr;
cnt += w.cnt;
idx++;
}
mArt.num = (short) cnt;
mArt.m_ver= ALG_RAIN_MAGIC;
for (int i = 0; i < mWets.size(); i++)
{
System.out.println("AAAAA mWets["+i+"].avr="+mWets.get(i).toString());
}
return cnt;
}
private int get_alg_rain_table_encode(int sample)
{
System.out.println("AAAAA sample="+sample);
for (AlgRain w: mWets)
{
System.out.println("AAAAA w="+w.toString());
if((sample > w.min) && (sample < w.max))
{
return w.idx;
}
}
return -1;
}
private int get_alg_rain_table_decode(int idx, byte code)
{
byte value;
if(idx%2 == 0)
{
value = (byte)(0x0F & code);
}
else
{
value = (byte)(0x0F & code >> 4);
}
return mArt.val[value];
}
private byte[] alg_rain_table_encode(AlgRainTable a)
{
int size = 2 + 2 + 4*WET_NUM ;
byte[] bb = new byte[size];
System.arraycopy(XiaoMiBigLittle.little_intToByte(a.m_ver, 2), 0, bb, 0, 2);
System.arraycopy(XiaoMiBigLittle.little_intToByte(a.num, 2), 0, bb, 2, 2);
for (int i = 0; i < WET_NUM; i++)
{
byte[] b = XiaoMiBigLittle.little_intToByte(a.val[i], 4);
for (int j = 0; j < b.length; j++)
{
System.out.println("AAAAA bbbb["+j+"]="+b[j]);
//System.arraycopy(b[j], 0, bb, 4+i*4+j, 1);
bb[4+i*4+j] = b[j];
}
//System.arraycopy(b, 0, bb, 4+i, 4);
}
return bb;
}
private AlgRainTable alg_rain_table_decode(byte[] b)
{
byte[] b1= new byte[2];
byte[] b2= new byte[4];
AlgRainTable a = new AlgRainTable();
System.arraycopy(b, 0, b1, 0, 2);
a.m_ver = (short)XiaoMiBigLittle.little_bytesToInt(b1);
System.arraycopy(b, 2, b1, 0, 2);
a.num = (short)XiaoMiBigLittle.little_bytesToInt(b1);
for (int i = 0; i < WET_NUM; i++)
{
System.arraycopy(b, 4 + i*4, b2, 0, 4);
a.val[i] = XiaoMiBigLittle.little_bytesToInt(b2);
}
return a;
}
public byte[] get_alg_rain_encode(int[] inSample)
{
int size = 2 + 2 + 4*WET_NUM ;
System.out.println("AAAAA size"+size);
byte [] outCode = new byte[inSample.length+size];
System.out.println("AAAAA inSample.length+size"+inSample.length+size);
for (int i : inSample)
{
alg_rain_feed(i);
}
alg_rain_feed_finish();
//int[] tmp = new int[68];
System.arraycopy(alg_rain_table_encode(mArt), 0, outCode, 0, size);
byte b2=0, b1=0;
for (int i = 0; i< inSample.length; i++)
{
b2 = (byte)get_alg_rain_table_encode(inSample[i]);
System.out.println("AAAAA b2="+b2+"inSample[i]="+inSample[i]);
if(i%2 == 0) //even low nibble
{
b1 = b2;
}
else{ //odd high nibble
b1 |= b2 << 4;
System.out.println("AAAAA b1="+b1);
outCode[size+i/2] = b1;
}
}
return outCode;
}
public int[] get_alg_rain_decode(byte[] inCode)
{
int size = 2 + 2 + 4*WET_NUM ;
AlgRainTable a = alg_rain_table_decode(inCode);
int[] outSmaple = new int[a.num];
System.out.println("AAAAA a.num="+a.num);
for (int i = 0; i < outSmaple.length; i++)
{
if ((i%2) == 0)
{
outSmaple[i] = a.val[inCode[size+(i/2)]&0x0f];
}else
{
outSmaple[i] = a.val[(inCode[size+(i/2)]>>4)&0x0f];
}
}
return outSmaple;
}
public static void main(String[] args) {
// init array
short a1[] = new short[100];
for (int i = 0; i < a1.length; i++) {
a1[i] = (short) ((i % 16) * 100 + 20);
System.out.println("AAAAA a1[" + i + "]=" + a1[i]);
}
// trans int
int a[] = new int[100];
for (int i = 0; i < a1.length; i++) {
if ((a1[i] & 0x8000) != 0) {
a[i] = 100 * (int) (a1[i] & 0x7FFF);
} else {
a[i] = a1[i];
}
System.out.println("AAAAA a[" + i + "]=" + a[i]);
}
// rain Encode
XiaoMiAlgRainEncode2 are = new XiaoMiAlgRainEncode2();
byte[] b = are.get_alg_rain_encode(a);
for (int i = 0; i < b.length; i++) {
System.out.println("AAAAA b[" + i + "]=" + b[i]);
}
// base64 Encode
byte[] eb64 = XiaoMiBase64.Base64Encode(b, b.length);
for (int i = 0; i < eb64.length; i++) {
System.out.println("AAAAA eb64[" + i + "]=" + eb64[i]);
}
// base64 decode
byte[] db64 = XiaoMiBase64.Base64Decode(eb64, eb64.length);
for (int i = 0; i < db64.length; i++) {
System.out.println("AAAAA db64[" + i + "]=" + db64[i]);
}
// rain decode
int[] c = are.get_alg_rain_decode(b);
for (int i = 0; i < c.length; i++) {
System.out.println("AAAAA c[" + i + "]=" + c[i]);
}
// trans short
for (int i = 0; i < c.length; i++) {
if (c[i] > 0x8000) {
a1[i] = (short) ((c[i] / 100) | 0x8000);
} else {
a1[i] = (short) c[i];
}
System.out.println("AAAAA a1[" + i + "]=" + a1[i]);
}
System.out.println("AAAAA the mechine is big ="
+ XiaoMiBigLittle.isBigendian());
}
}