| 154 | |
| 155 | |
| 156 | def _learn_best_quantization(luts): # luts can be a bunch of vstacked luts |
| 157 | best_loss = np.inf |
| 158 | best_alpha = None |
| 159 | best_floors = None |
| 160 | best_scale_by = None |
| 161 | for alpha in [.001, .002, .005, .01, .02, .05, .1]: |
| 162 | alpha_pct = int(100 * alpha) |
| 163 | |
| 164 | # compute quantized luts this alpha would yield |
| 165 | floors = np.percentile(luts, alpha_pct, axis=0) |
| 166 | luts_offset = np.maximum(0, luts - floors) |
| 167 | |
| 168 | ceil = np.percentile(luts_offset, 100 - alpha_pct) |
| 169 | scale_by = 255. / ceil |
| 170 | luts_quantized = np.floor(luts_offset * scale_by).astype(np.int) |
| 171 | luts_quantized = np.minimum(255, luts_quantized) |
| 172 | |
| 173 | # compute err |
| 174 | luts_ideal = (luts - luts_offset) * scale_by |
| 175 | diffs = luts_ideal - luts_quantized |
| 176 | loss = np.sum(diffs * diffs) |
| 177 | |
| 178 | if loss <= best_loss: |
| 179 | best_loss = loss |
| 180 | best_alpha = alpha |
| 181 | best_floors = floors |
| 182 | best_scale_by = scale_by |
| 183 | |
| 184 | return best_floors, best_scale_by, best_alpha |
| 185 | |
| 186 | |
| 187 | class OPQEncoder(PQEncoder): |