Skip to content

Commit 79d0f6c

Browse files
committed
Change TrainW bias, don't recluster when splitting
This seems to improve PSNR by 0.1~1.0dB in most of my tests
1 parent 9d027e5 commit 79d0f6c

File tree

1 file changed

+22
-18
lines changed

1 file changed

+22
-18
lines changed

Quantize.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ static inline void QuantCluster_Train(struct QuantCluster_t *Dst, const struct B
1515
struct BGRAf_t Dist = BGRAf_Sub(Data, &Dst->Centroid);
1616

1717
float DistW = BGRAf_Len2(&Dist);
18-
float TrainW = 0.001f + DistW; //! <- This will help outliers pop out more often (must not be 0.0!)
18+
float TrainW = 0.01f + DistW; //! <- This will help outliers pop out more often (must not be 0.0!)
1919
DistW *= 1.0f + fabsf(Dist.b); //! <- Further penalize distortion by luma distortion
2020
struct BGRAf_t TrainData = BGRAf_Muli( Data, TrainW);
2121
struct BGRAf_t DistData = BGRAf_Muli(&Dist, DistW);
@@ -31,28 +31,30 @@ static inline int QuantCluster_Resolve(struct QuantCluster_t *x) {
3131
}
3232

3333
//! Split a quantization cluster
34-
static inline void QuantCluster_Split(struct QuantCluster_t *Clusters, int SrcCluster, int DstCluster, const struct BGRAf_t *Data, int nData, int32_t *DataClusters) {
34+
static inline void QuantCluster_Split(struct QuantCluster_t *Clusters, int SrcCluster, int DstCluster, const struct BGRAf_t *Data, int nData, int32_t *DataClusters, int Recluster) {
3535
//! Shift the cluster in either direction of the distortion vector
3636
struct BGRAf_t Dist = BGRAf_Divi(&Clusters[SrcCluster].Dist, Clusters[SrcCluster].DistWeight);
3737
Clusters[DstCluster].Centroid = BGRAf_Add(&Clusters[SrcCluster].Centroid, &Dist);
3838
Clusters[SrcCluster].Centroid = BGRAf_Sub(&Clusters[SrcCluster].Centroid, &Dist);
3939

4040
//! Re-assign clusters
41-
int n;
42-
QuantCluster_ClearTraining(&Clusters[SrcCluster]);
43-
QuantCluster_ClearTraining(&Clusters[DstCluster]);
44-
for(n=0;n<nData;n++) if(DataClusters[n] == SrcCluster) {
45-
float DistSrc = BGRAf_ColDistance(&Data[n], &Clusters[SrcCluster].Centroid);
46-
float DistDst = BGRAf_ColDistance(&Data[n], &Clusters[DstCluster].Centroid);
47-
if(DistSrc < DistDst) {
48-
QuantCluster_Train(&Clusters[SrcCluster], &Data[n]);
49-
} else {
50-
QuantCluster_Train(&Clusters[DstCluster], &Data[n]);
51-
DataClusters[n] = DstCluster;
41+
if(Recluster) {
42+
int n;
43+
QuantCluster_ClearTraining(&Clusters[SrcCluster]);
44+
QuantCluster_ClearTraining(&Clusters[DstCluster]);
45+
for(n=0;n<nData;n++) if(DataClusters[n] == SrcCluster) {
46+
float DistSrc = BGRAf_ColDistance(&Data[n], &Clusters[SrcCluster].Centroid);
47+
float DistDst = BGRAf_ColDistance(&Data[n], &Clusters[DstCluster].Centroid);
48+
if(DistSrc < DistDst) {
49+
QuantCluster_Train(&Clusters[SrcCluster], &Data[n]);
50+
} else {
51+
QuantCluster_Train(&Clusters[DstCluster], &Data[n]);
52+
DataClusters[n] = DstCluster;
53+
}
5254
}
55+
QuantCluster_Resolve(&Clusters[SrcCluster]);
56+
QuantCluster_Resolve(&Clusters[DstCluster]);
5357
}
54-
QuantCluster_Resolve(&Clusters[SrcCluster]);
55-
QuantCluster_Resolve(&Clusters[DstCluster]);
5658
}
5759

5860
/**************************************/
@@ -117,8 +119,10 @@ void QuantCluster_Quantize(struct QuantCluster_t *Clusters, int nCluster, const
117119
if(EmptyCluster != -1) DstCluster = EmptyCluster, EmptyCluster = Clusters[EmptyCluster].Next;
118120
else DstCluster = nClusterCur++;
119121

120-
//! Split and recluster
121-
QuantCluster_Split(Clusters, MaxDistCluster, DstCluster, Data, nData, DataClusters);
122+
//! Split cluster, but do NOT recluster the data.
123+
//! By not re-clustering, we give outliers a better chance
124+
//! of making it through to a better-fitting cluster.
125+
QuantCluster_Split(Clusters, MaxDistCluster, DstCluster, Data, nData, DataClusters, 0);
122126

123127
//! Check if we have more clusters that need splitting
124128
MaxDistCluster = Clusters[MaxDistCluster].Next;
@@ -159,7 +163,7 @@ void QuantCluster_Quantize(struct QuantCluster_t *Clusters, int nCluster, const
159163

160164
//! Split the most distorted clusters into any empty ones
161165
while(EmptyCluster != -1 && MaxDistCluster != -1) {
162-
QuantCluster_Split(Clusters, MaxDistCluster, EmptyCluster, Data, nData, DataClusters);
166+
QuantCluster_Split(Clusters, MaxDistCluster, EmptyCluster, Data, nData, DataClusters, 1);
163167
MaxDistCluster = Clusters[MaxDistCluster].Next;
164168
EmptyCluster = Clusters[EmptyCluster].Next;
165169
}

0 commit comments

Comments
 (0)