107#include <config_auto.h>
112#include "allheaders.h"
115static const l_float32 TINY = 0.00001f;
118 l_int32 *pnx, l_int32 *pny, l_int32 debug);
120 l_int32 factor, l_int32 n,
121 l_float32 *pscore,
PIXA *pixadebug);
188l_int32 w1, h1, d1, w2, h2, d2, wpl1, wpl2;
189l_int32 spp1, spp2, i, j, color, mismatch, opaque;
190l_int32 fullwords, linebits, endbits;
191l_uint32 endmask, wordmask;
192l_uint32 *data1, *data2, *line1, *line2;
193PIX *pixs1, *pixs2, *pixt1, *pixt2, *pixalpha;
197 return ERROR_INT(
"psame not defined", __func__, 1);
200 return ERROR_INT(
"pix1 and pix2 not both defined", __func__, 1);
201 pixGetDimensions(pix1, &w1, &h1, &d1);
202 pixGetDimensions(pix2, &w2, &h2, &d2);
203 if (w1 != w2 || h1 != h2) {
204 L_INFO(
"pix sizes differ\n", __func__);
215 spp1 = pixGetSpp(pix1);
216 spp2 = pixGetSpp(pix2);
218 if (use_alpha && d1 == 32 && d2 == 32) {
219 mismatch = ((spp1 == 4 && spp2 != 4) || (spp1 != 4 && spp2 == 4));
221 pixalpha = (spp1 == 4) ? pix1 : pix2;
222 pixAlphaIsOpaque(pixalpha, &opaque);
224 L_INFO(
"just one pix has a non-opaque alpha layer\n", __func__);
230 cmap1 = pixGetColormap(pix1);
231 cmap2 = pixGetColormap(pix2);
232 if (!cmap1 && !cmap2 && (d1 != d2) && (d1 == 32 || d2 == 32)) {
233 L_INFO(
"no colormaps, pix depths unequal, and one of them is RGB\n",
238 if (cmap1 && cmap2 && (d1 == d2))
243 if (cmap1 && !cmap2) {
245 if (color && d2 <= 8)
248 pixs2 = pixConvertTo8(pix2, FALSE);
250 pixs2 = pixClone(pix2);
255 }
else if (!cmap1 && cmap2) {
257 if (color && d1 <= 8)
260 pixs1 = pixConvertTo8(pix1, FALSE);
262 pixs1 = pixClone(pix1);
267 }
else if (cmap1 && cmap2) {
271 pixs1 = pixClone(pix1);
272 pixs2 = pixClone(pix2);
276 d1 = pixGetDepth(pixs1);
277 d2 = pixGetDepth(pixs2);
279 if (d1 == 16 || d2 == 16) {
280 L_INFO(
"one pix is 16 bpp\n", __func__);
285 pixt1 = pixConvertLossless(pixs1, 8);
286 pixt2 = pixConvertLossless(pixs2, 8);
287 if (!pixt1 || !pixt2) {
288 L_INFO(
"failure to convert to 8 bpp\n", __func__);
296 pixt1 = pixClone(pixs1);
297 pixt2 = pixClone(pixs2);
303 d1 = pixGetDepth(pixt1);
304 d2 = pixGetDepth(pixt2);
305 wpl1 = pixGetWpl(pixt1);
306 wpl2 = pixGetWpl(pixt2);
307 data1 = pixGetData(pixt1);
308 data2 = pixGetData(pixt2);
311 if (use_alpha && !mismatch)
312 wordmask = (spp1 == 3) ? 0xffffff00 : 0xffffffff;
314 wordmask = 0xffffff00;
315 for (i = 0; i < h1; i++) {
316 line1 = data1 + wpl1 * i;
317 line2 = data2 + wpl2 * i;
318 for (j = 0; j < wpl1; j++) {
319 if ((*line1 ^ *line2) & wordmask) {
330 fullwords = linebits / 32;
331 endbits = linebits & 31;
332 endmask = (endbits == 0) ? 0 : (0xffffffff << (32 - endbits));
333 for (i = 0; i < h1; i++) {
334 line1 = data1 + wpl1 * i;
335 line2 = data2 + wpl2 * i;
336 for (j = 0; j < fullwords; j++) {
337 if (*line1 ^ *line2) {
346 if ((*line1 ^ *line2) & endmask) {
387l_int32 d, w, h, wpl1, wpl2, i, j, linebits, fullwords, endbits;
388l_int32 rval1, rval2, gval1, gval2, bval1, bval2, samecmaps;
389l_uint32 endmask, val1, val2;
390l_uint32 *data1, *data2, *line1, *line2;
394 return ERROR_INT(
"&same not defined", __func__, 1);
397 return ERROR_INT(
"pix1 not defined", __func__, 1);
399 return ERROR_INT(
"pix2 not defined", __func__, 1);
401 if (pixSizesEqual(pix1, pix2) == 0)
403 cmap1 = pixGetColormap(pix1);
404 cmap2 = pixGetColormap(pix2);
405 if (!cmap1 || !cmap2) {
406 L_INFO(
"both images don't have colormap\n", __func__);
409 pixGetDimensions(pix1, &w, &h, &d);
410 if (d != 1 && d != 2 && d != 4 && d != 8) {
411 L_INFO(
"pix depth not in {1, 2, 4, 8}\n", __func__);
416 if (samecmaps == TRUE) {
418 wpl1 = pixGetWpl(pix1);
419 wpl2 = pixGetWpl(pix2);
420 data1 = pixGetData(pix1);
421 data2 = pixGetData(pix2);
422 fullwords = linebits / 32;
423 endbits = linebits & 31;
424 endmask = (endbits == 0) ? 0 : (0xffffffff << (32 - endbits));
425 for (i = 0; i < h; i++) {
426 line1 = data1 + wpl1 * i;
427 line2 = data2 + wpl2 * i;
428 for (j = 0; j < fullwords; j++) {
435 if ((*line1 ^ *line2) & endmask)
444 for (i = 0; i < h; i++) {
445 for (j = 0; j < w; j++) {
446 pixGetPixel(pix1, j, i, &val1);
447 pixGetPixel(pix2, j, i, &val2);
448 pixcmapGetColor(cmap1, val1, &rval1, &gval1, &bval1);
449 pixcmapGetColor(cmap2, val2, &rval2, &gval2, &bval2);
450 if (rval1 != rval2 || gval1 != gval2 || bval1 != bval2)
482l_int32 n1, n2, i, rval1, rval2, gval1, gval2, bval1, bval2, aval1, aval2;
485 return ERROR_INT(
"&same not defined", __func__, 1);
488 return ERROR_INT(
"cmap1 not defined", __func__, 1);
490 return ERROR_INT(
"cmap2 not defined", __func__, 1);
491 if (ncomps != 3 && ncomps != 4)
492 return ERROR_INT(
"ncomps not 3 or 4", __func__, 1);
494 n1 = pixcmapGetCount(cmap1);
495 n2 = pixcmapGetCount(cmap2);
497 L_INFO(
"colormap sizes are different\n", __func__);
501 for (i = 0; i < n1; i++) {
502 pixcmapGetRGBA(cmap1, i, &rval1, &gval1, &bval1, &aval1);
503 pixcmapGetRGBA(cmap2, i, &rval2, &gval2, &bval2, &aval2);
504 if (rval1 != rval2 || gval1 != gval2 || bval1 != bval2)
506 if (ncomps == 4 && aval1 != aval2)
536l_int32 n, i, rval, gval, bval, numpix;
541 return ERROR_INT(
"&color not defined", __func__, 1);
544 return ERROR_INT(
"pixs not defined", __func__, 1);
546 if ((cmap = pixGetColormap(pixs)) == NULL)
549 pixcmapHasColor(cmap, pcolor);
554 na = pixGetGrayHistogram(pixs, 1);
555 n = pixcmapGetCount(cmap);
556 for (i = 0; i < n; i++) {
557 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
558 numaGetIValue(na, i, &numpix);
559 if ((rval != gval || rval != bval) && numpix) {
601l_int32 count1, count2, countn;
606 return ERROR_INT(
"&pval not defined", __func__, 1);
609 return ERROR_INT(
"pix1 not defined", __func__, 1);
611 return ERROR_INT(
"pix2 not defined", __func__, 1);
613 tab8 = makePixelSumTab8();
614 pixCountPixels(pix1, &count1, tab8);
615 pixCountPixels(pix2, &count2, tab8);
616 if (count1 == 0 || count2 == 0) {
620 pixn = pixAnd(NULL, pix1, pix2);
621 pixCountPixels(pixn, &countn, tab8);
622 *pval = (l_float32)countn * (l_float32)countn /
623 ((l_float32)count1 * (l_float32)count2);
663l_int32 i, j, w1, h1, d1, w2, h2, d2, minw, minh, wpl1, wpl2, wpl3;
664l_int32 rval1, gval1, bval1, rval2, gval2, bval2;
666l_uint32 *data1, *data2, *data3, *line1, *line2, *line3;
667PIX *pix3 = NULL, *pix4 = NULL, *pixd;
671 return (
PIX *)ERROR_PTR(
"pix1, pix2 not both defined", __func__, NULL);
672 pixGetDimensions(pix1, &w1, &h1, &d1);
673 pixGetDimensions(pix2, &w2, &h2, &d2);
675 return (
PIX *)ERROR_PTR(
"unequal depths", __func__, NULL);
677 return (
PIX *)ERROR_PTR(
"mindiff must be > 0", __func__, NULL);
681 pixd = pixConvertTo32(pix3);
684 minw = L_MIN(w1, w2);
685 minh = L_MIN(h1, h2);
686 pix3 = pixConvertTo32(pix1);
687 pix4 = pixConvertTo32(pix2);
688 pixd = pixCreate(minw, minh, 32);
689 pixRasterop(pixd, 0, 0, minw, minh,
PIX_SRC, pix3, 0, 0);
690 data1 = pixGetData(pix3);
691 wpl1 = pixGetWpl(pix3);
692 data2 = pixGetData(pix4);
693 wpl2 = pixGetWpl(pix4);
694 data3 = pixGetData(pixd);
695 wpl3 = pixGetWpl(pixd);
696 for (i = 0; i < minh; i++) {
697 line1 = data1 + i * wpl1;
698 line2 = data2 + i * wpl2;
699 line3 = data3 + i * wpl3;
700 for (j = 0; j < minw; j++) {
703 extractRGBValues(val1, &rval1, &gval1, &bval1);
704 extractRGBValues(val2, &rval2, &gval2, &bval2);
705 if (L_ABS(rval1 - rval2) >= mindiff ||
706 L_ABS(gval1 - gval2) >= mindiff ||
707 L_ABS(bval1 - bval2) >= mindiff)
714 pixa1 = pixaCreate(3);
716 pixaAddPix(pixa1, pix1,
L_COPY);
717 pixaAddPix(pixa1, pix2,
L_COPY);
723 pixd = pixaDisplayTiledInColumns(pixa1, 2, 1.0, 30, 2);
753l_int32 w1, h1, d1, w2, h2, d2, minw, minh;
758 return (
PIX *)ERROR_PTR(
"pix1, pix2 not both defined", __func__, NULL);
759 pixGetDimensions(pix1, &w1, &h1, &d1);
760 pixGetDimensions(pix2, &w2, &h2, &d2);
761 if (d1 != 1 || d2 != 1)
762 return (
PIX *)ERROR_PTR(
"pix1 and pix2 not 1 bpp", __func__, NULL);
763 minw = L_MIN(w1, w2);
764 minh = L_MIN(h1, h2);
766 pixd = pixCreate(minw, minh, 4);
767 cmap = pixcmapCreate(4);
768 pixcmapAddColor(cmap, 255, 255, 255);
769 pixcmapAddColor(cmap, 0, 0, 0);
770 pixcmapAddColor(cmap, 255, 0, 0);
771 pixcmapAddColor(cmap, 0, 255, 0);
772 pixSetColormap(pixd, cmap);
774 pixt = pixAnd(NULL, pix1, pix2);
775 pixPaintThroughMask(pixd, pixt, 0, 0, 0x0);
776 pixSubtract(pixt, pix1, pix2);
777 pixPaintThroughMask(pixd, pixt, 0, 0, 0xff000000);
778 pixSubtract(pixt, pix2, pix1);
779 pixPaintThroughMask(pixd, pixt, 0, 0, 0x00ff0000);
814 if (ppixdiff) *ppixdiff = NULL;
816 return ERROR_INT(
"&pfract not defined", __func__, 1);
818 if (!pix1 || pixGetDepth(pix1) != 1)
819 return ERROR_INT(
"pix1 not defined or not 1 bpp", __func__, 1);
820 if (!pix2 || pixGetDepth(pix2) != 1)
821 return ERROR_INT(
"pix2 not defined or not 1 bpp", __func__, 1);
822 if (comptype != L_COMPARE_XOR && comptype != L_COMPARE_SUBTRACT)
823 return ERROR_INT(
"invalid comptype", __func__, 1);
825 if (comptype == L_COMPARE_XOR)
826 pixt = pixXor(NULL, pix1, pix2);
828 pixt = pixSubtract(NULL, pix1, pix2);
829 pixCountPixels(pixt, &count, NULL);
830 pixGetDimensions(pix1, &w, &h, NULL);
831 *pfract = (l_float32)(count) / (l_float32)(w * h);
892l_int32 retval, d1, d2;
893PIX *pixt1, *pixt2, *pixs1, *pixs2;
895 if (psame) *psame = 0;
896 if (pdiff) *pdiff = 255.0;
897 if (prmsdiff) *prmsdiff = 255.0;
898 if (ppixdiff) *ppixdiff = NULL;
899 if (!pix1 || pixGetDepth(pix1) == 1)
900 return ERROR_INT(
"pix1 not defined or 1 bpp", __func__, 1);
901 if (!pix2 || pixGetDepth(pix2) == 1)
902 return ERROR_INT(
"pix2 not defined or 1 bpp", __func__, 1);
903 if (comptype != L_COMPARE_SUBTRACT && comptype != L_COMPARE_ABS_DIFF)
904 return ERROR_INT(
"invalid comptype", __func__, 1);
905 if (plottype < 0 || plottype >= NUM_GPLOT_OUTPUTS)
906 return ERROR_INT(
"invalid plottype", __func__, 1);
910 d1 = pixGetDepth(pixt1);
911 d2 = pixGetDepth(pixt2);
913 pixs1 = pixConvertTo8(pixt1, FALSE);
915 pixs1 = pixClone(pixt1);
917 pixs2 = pixConvertTo8(pixt2, FALSE);
919 pixs2 = pixClone(pixt2);
922 d1 = pixGetDepth(pixs1);
923 d2 = pixGetDepth(pixs2);
927 return ERROR_INT(
"intrinsic depths are not equal", __func__, 1);
930 if (d1 == 8 || d1 == 16)
932 pdiff, prmsdiff, ppixdiff);
934 retval =
pixCompareRGB(pixs1, pixs2, comptype, plottype, psame,
935 pdiff, prmsdiff, ppixdiff);
974static l_atomic index = 0;
975l_int32 d1, d2, same, first, last;
980 if (psame) *psame = 0;
981 if (pdiff) *pdiff = 255.0;
982 if (prmsdiff) *prmsdiff = 255.0;
983 if (ppixdiff) *ppixdiff = NULL;
985 return ERROR_INT(
"pix1 not defined", __func__, 1);
987 return ERROR_INT(
"pix2 not defined", __func__, 1);
988 d1 = pixGetDepth(pix1);
989 d2 = pixGetDepth(pix2);
990 if ((d1 != d2) || (d1 != 8 && d1 != 16))
991 return ERROR_INT(
"depths unequal or not 8 or 16 bpp", __func__, 1);
992 if (pixGetColormap(pix1) || pixGetColormap(pix2))
993 return ERROR_INT(
"pix1 and/or pix2 are colormapped", __func__, 1);
994 if (comptype != L_COMPARE_SUBTRACT && comptype != L_COMPARE_ABS_DIFF)
995 return ERROR_INT(
"invalid comptype", __func__, 1);
996 if (plottype < 0 || plottype >= NUM_GPLOT_OUTPUTS)
997 return ERROR_INT(
"invalid plottype", __func__, 1);
999 lept_mkdir(
"lept/comp");
1001 if (comptype == L_COMPARE_SUBTRACT)
1002 pixt = pixSubtractGray(NULL, pix1, pix2);
1004 pixt = pixAbsDifference(pix1, pix2);
1006 pixZero(pixt, &same);
1008 L_INFO(
"Images are pixel-wise identical\n", __func__);
1009 if (psame) *psame = same;
1012 pixGetAverageMasked(pixt, NULL, 0, 0, 1,
L_MEAN_ABSVAL, pdiff);
1015 if (plottype && !same) {
1016 L_INFO(
"Images differ: output plots will be generated\n", __func__);
1017 na = pixGetGrayHistogram(pixt, 1);
1018 numaGetNonzeroRange(na, TINY, &first, &last);
1019 nac = numaClipToInterval(na, 0, last);
1020 snprintf(buf,
sizeof(buf),
"/tmp/lept/comp/compare_gray%d", index);
1021 gplot = gplotCreate(buf, plottype,
1022 "Pixel Difference Histogram",
"diff val",
1023 "number of pixels");
1024 gplotAddPlot(gplot, NULL, nac, GPLOT_LINES,
"gray");
1025 gplotMakeOutput(gplot);
1026 gplotDestroy(&gplot);
1027 snprintf(buf,
sizeof(buf),
"/tmp/lept/comp/compare_gray%d.png",
1029 l_fileDisplay(buf, 100, 100, 1.0);
1035 *ppixdiff = pixCopy(NULL, pixt);
1038 if (comptype == L_COMPARE_SUBTRACT) {
1040 pixt = pixAbsDifference(pix1, pix2);
1077 l_float32 *prmsdiff,
1081static l_atomic index = 0;
1082l_int32 rsame, gsame, bsame, same, first, rlast, glast, blast, last;
1083l_float32 rdiff, gdiff, bdiff;
1085NUMA *nar, *nag, *nab, *narc, *nagc, *nabc;
1086PIX *pixr1, *pixr2, *pixg1, *pixg2, *pixb1, *pixb2;
1087PIX *pixr, *pixg, *pixb;
1089 if (psame) *psame = 0;
1090 if (pdiff) *pdiff = 0.0;
1091 if (prmsdiff) *prmsdiff = 0.0;
1092 if (ppixdiff) *ppixdiff = NULL;
1093 if (!pix1 || pixGetDepth(pix1) != 32)
1094 return ERROR_INT(
"pix1 not defined or not 32 bpp", __func__, 1);
1095 if (!pix2 || pixGetDepth(pix2) != 32)
1096 return ERROR_INT(
"pix2 not defined or not ew bpp", __func__, 1);
1097 if (comptype != L_COMPARE_SUBTRACT && comptype != L_COMPARE_ABS_DIFF)
1098 return ERROR_INT(
"invalid comptype", __func__, 1);
1099 if (plottype < 0 || plottype >= NUM_GPLOT_OUTPUTS)
1100 return ERROR_INT(
"invalid plottype", __func__, 1);
1102 lept_mkdir(
"lept/comp");
1104 pixr1 = pixGetRGBComponent(pix1,
COLOR_RED);
1105 pixr2 = pixGetRGBComponent(pix2,
COLOR_RED);
1108 pixb1 = pixGetRGBComponent(pix1,
COLOR_BLUE);
1109 pixb2 = pixGetRGBComponent(pix2,
COLOR_BLUE);
1110 if (comptype == L_COMPARE_SUBTRACT) {
1111 pixr = pixSubtractGray(NULL, pixr1, pixr2);
1112 pixg = pixSubtractGray(NULL, pixg1, pixg2);
1113 pixb = pixSubtractGray(NULL, pixb1, pixb2);
1115 pixr = pixAbsDifference(pixr1, pixr2);
1116 pixg = pixAbsDifference(pixg1, pixg2);
1117 pixb = pixAbsDifference(pixb1, pixb2);
1120 pixZero(pixr, &rsame);
1121 pixZero(pixg, &gsame);
1122 pixZero(pixb, &bsame);
1123 same = rsame && gsame && bsame;
1125 L_INFO(
"Images are pixel-wise identical\n", __func__);
1126 if (psame) *psame = same;
1129 pixGetAverageMasked(pixr, NULL, 0, 0, 1,
L_MEAN_ABSVAL, &rdiff);
1130 pixGetAverageMasked(pixg, NULL, 0, 0, 1,
L_MEAN_ABSVAL, &gdiff);
1131 pixGetAverageMasked(pixb, NULL, 0, 0, 1,
L_MEAN_ABSVAL, &bdiff);
1132 *pdiff = (rdiff + gdiff + bdiff) / 3.0;
1136 if (plottype && !same) {
1137 L_INFO(
"Images differ: output plots will be generated\n", __func__);
1138 nar = pixGetGrayHistogram(pixr, 1);
1139 nag = pixGetGrayHistogram(pixg, 1);
1140 nab = pixGetGrayHistogram(pixb, 1);
1141 numaGetNonzeroRange(nar, TINY, &first, &rlast);
1142 numaGetNonzeroRange(nag, TINY, &first, &glast);
1143 numaGetNonzeroRange(nab, TINY, &first, &blast);
1144 last = L_MAX(rlast, glast);
1145 last = L_MAX(last, blast);
1146 narc = numaClipToInterval(nar, 0, last);
1147 nagc = numaClipToInterval(nag, 0, last);
1148 nabc = numaClipToInterval(nab, 0, last);
1149 snprintf(buf,
sizeof(buf),
"/tmp/lept/comp/compare_rgb%d", index);
1150 gplot = gplotCreate(buf, plottype,
1151 "Pixel Difference Histogram",
"diff val",
1152 "number of pixels");
1153 gplotAddPlot(gplot, NULL, narc, GPLOT_LINES,
"red");
1154 gplotAddPlot(gplot, NULL, nagc, GPLOT_LINES,
"green");
1155 gplotAddPlot(gplot, NULL, nabc, GPLOT_LINES,
"blue");
1156 gplotMakeOutput(gplot);
1157 gplotDestroy(&gplot);
1158 snprintf(buf,
sizeof(buf),
"/tmp/lept/comp/compare_rgb%d.png",
1160 l_fileDisplay(buf, 100, 100, 1.0);
1170 *ppixdiff = pixCreateRGBImage(pixr, pixg, pixb);
1173 if (comptype == L_COMPARE_SUBTRACT) {
1177 pixr = pixAbsDifference(pixr1, pixr2);
1178 pixg = pixAbsDifference(pixg1, pixg2);
1179 pixb = pixAbsDifference(pixb1, pixb2);
1184 *prmsdiff = (rdiff + gdiff + bdiff) / 3.0;
1232l_int32 d1, d2, w, h;
1233PIX *pixt, *pixr, *pixg, *pixb;
1234PIX *pixrdiff, *pixgdiff, *pixbdiff;
1238 return ERROR_INT(
"&pixdiff not defined", __func__, 1);
1241 return ERROR_INT(
"pix1 not defined", __func__, 1);
1243 return ERROR_INT(
"pix2 not defined", __func__, 1);
1244 d1 = pixGetDepth(pix1);
1245 d2 = pixGetDepth(pix2);
1247 return ERROR_INT(
"depths not equal", __func__, 1);
1248 if (d1 != 8 && d1 != 32)
1249 return ERROR_INT(
"pix1 not 8 or 32 bpp", __func__, 1);
1250 if (d2 != 8 && d2 != 32)
1251 return ERROR_INT(
"pix2 not 8 or 32 bpp", __func__, 1);
1252 if (sx < 2 || sy < 2)
1253 return ERROR_INT(
"sx and sy not both > 1", __func__, 1);
1255 return ERROR_INT(
"invalid type", __func__, 1);
1257 pixt = pixAbsDifference(pix1, pix2);
1259 *ppixdiff = pixGetAverageTiled(pixt, sx, sy, type);
1261 pixr = pixGetRGBComponent(pixt,
COLOR_RED);
1264 pixrdiff = pixGetAverageTiled(pixr, sx, sy, type);
1265 pixgdiff = pixGetAverageTiled(pixg, sx, sy, type);
1266 pixbdiff = pixGetAverageTiled(pixb, sx, sy, type);
1267 pixGetDimensions(pixrdiff, &w, &h, NULL);
1268 pixacc = pixaccCreate(w, h, 0);
1269 pixaccAdd(pixacc, pixrdiff);
1270 pixaccAdd(pixacc, pixgdiff);
1271 pixaccAdd(pixacc, pixbdiff);
1272 pixaccMultConst(pixacc, 1.f / 3.f);
1273 *ppixdiff = pixaccFinal(pixacc, 8);
1277 pixDestroy(&pixrdiff);
1278 pixDestroy(&pixgdiff);
1279 pixDestroy(&pixbdiff);
1280 pixaccDestroy(&pixacc);
1322l_float32 *array1, *array2;
1323NUMA *nah, *nan, *nad;
1326 return (
NUMA *)ERROR_PTR(
"pix1 not defined", __func__, NULL);
1328 return (
NUMA *)ERROR_PTR(
"pix2 not defined", __func__, NULL);
1331 return (
NUMA *)ERROR_PTR(
"na not made", __func__, NULL);
1333 nan = numaNormalizeHistogram(nah, 1.0);
1334 array1 = numaGetFArray(nan,
L_NOCOPY);
1336 nad = numaCreate(256);
1337 numaSetCount(nad, 256);
1338 array2 = numaGetFArray(nad,
L_NOCOPY);
1342 for (i = 1; i < 256; i++)
1343 array2[i] = array2[i - 1] - array1[i - 1];
1409l_float32 fractdiff, avediff;
1412 return ERROR_INT(
"&similar not defined", __func__, 1);
1415 return ERROR_INT(
"pix1 not defined", __func__, 1);
1417 return ERROR_INT(
"pix2 not defined", __func__, 1);
1418 if (pixSizesEqual(pix1, pix2) == 0)
1419 return ERROR_INT(
"pix sizes not equal", __func__, 1);
1421 return ERROR_INT(
"mindiff must be > 0", __func__, 1);
1424 &fractdiff, &avediff, details))
1425 return ERROR_INT(
"diff stats not found", __func__, 1);
1427 if (maxave <= 0.0) maxave = 256.0;
1428 if (fractdiff <= maxfract && avediff <= maxave)
1481 l_float32 *pfractdiff,
1482 l_float32 *pavediff,
1485l_int32 i, first, last, diff;
1486l_float32 fract, ave;
1488NUMA *nah, *nan, *nac;
1490 if (pfractdiff) *pfractdiff = 0.0;
1491 if (pavediff) *pavediff = 0.0;
1493 return ERROR_INT(
"&fractdiff not defined", __func__, 1);
1495 return ERROR_INT(
"&avediff not defined", __func__, 1);
1497 return ERROR_INT(
"pix1 not defined", __func__, 1);
1499 return ERROR_INT(
"pix2 not defined", __func__, 1);
1501 return ERROR_INT(
"mindiff must be > 0", __func__, 1);
1504 return ERROR_INT(
"na not made", __func__, 1);
1506 if ((nan = numaNormalizeHistogram(nah, 1.0)) == NULL) {
1508 return ERROR_INT(
"nan not made", __func__, 1);
1510 array = numaGetFArray(nan,
L_NOCOPY);
1513 lept_mkdir(
"lept/comp");
1514 numaGetNonzeroRange(nan, 0.0, &first, &last);
1515 nac = numaClipToInterval(nan, first, last);
1516 gplotSimple1(nac, GPLOT_PNG,
"/tmp/lept/comp/histo",
1517 "Difference histogram");
1518 l_fileDisplay(
"/tmp/lept/comp/histo.png", 500, 0, 1.0);
1519 lept_stderr(
"\nNonzero values in normalized histogram:");
1520 numaWriteStderr(nac);
1522 lept_stderr(
" Mindiff fractdiff avediff\n");
1523 lept_stderr(
" -----------------------------------\n");
1524 for (diff = 1; diff < L_MIN(2 * mindiff, last); diff++) {
1527 for (i = diff; i <= last; i++) {
1529 ave += (l_float32)i * array[i];
1531 ave = (fract == 0.0) ? 0.0 : ave / fract;
1533 lept_stderr(
"%5d %7.4f %7.4f\n",
1536 lept_stderr(
" -----------------------------------\n");
1541 for (i = mindiff; i < 256; i++) {
1543 ave += (l_float32)i * array[i];
1545 ave = (fract == 0.0) ? 0.0 : ave / fract;
1548 *pfractdiff = fract;
1581l_int32 w1, h1, d1, w2, h2, d2, w, h, wpl1, wpl2;
1582l_int32 i, j, val, val1, val2;
1583l_int32 rval1, rval2, gval1, gval2, bval1, bval2;
1584l_int32 rdiff, gdiff, bdiff, maxdiff;
1585l_uint32 *data1, *data2, *line1, *line2;
1591 return (
NUMA *)ERROR_PTR(
"pix1 not defined", __func__, NULL);
1593 return (
NUMA *)ERROR_PTR(
"pix2 not defined", __func__, NULL);
1594 d1 = pixGetDepth(pix1);
1595 d2 = pixGetDepth(pix2);
1596 if (d1 == 16 || d2 == 16)
1597 return (
NUMA *)ERROR_PTR(
"d == 16 not supported", __func__, NULL);
1598 if (d1 < 8 && !pixGetColormap(pix1))
1599 return (
NUMA *)ERROR_PTR(
"pix1 depth < 8 bpp and not cmapped",
1601 if (d2 < 8 && !pixGetColormap(pix2))
1602 return (
NUMA *)ERROR_PTR(
"pix2 depth < 8 bpp and not cmapped",
1606 pixGetDimensions(pixt1, &w1, &h1, &d1);
1607 pixGetDimensions(pixt2, &w2, &h2, &d2);
1611 return (
NUMA *)ERROR_PTR(
"pix depths not equal", __func__, NULL);
1613 if (factor < 1) factor = 1;
1615 na = numaCreate(256);
1616 numaSetCount(na, 256);
1617 array = numaGetFArray(na,
L_NOCOPY);
1620 data1 = pixGetData(pixt1);
1621 data2 = pixGetData(pixt2);
1622 wpl1 = pixGetWpl(pixt1);
1623 wpl2 = pixGetWpl(pixt2);
1625 for (i = 0; i < h; i += factor) {
1626 line1 = data1 + i * wpl1;
1627 line2 = data2 + i * wpl2;
1628 for (j = 0; j < w; j += factor) {
1631 val = L_ABS(val1 - val2);
1636 for (i = 0; i < h; i += factor) {
1637 line1 = data1 + i * wpl1;
1638 line2 = data2 + i * wpl2;
1639 for (j = 0; j < w; j += factor) {
1640 extractRGBValues(line1[j], &rval1, &gval1, &bval1);
1641 extractRGBValues(line2[j], &rval2, &gval2, &bval2);
1642 rdiff = L_ABS(rval1 - rval2);
1643 gdiff = L_ABS(gval1 - gval2);
1644 bdiff = L_ABS(bval1 - bval2);
1645 maxdiff = L_MAX(rdiff, gdiff);
1646 maxdiff = L_MAX(maxdiff, bdiff);
1715l_int32 d1, d2, w, h, count;
1716PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8, *pix9;
1719 if (ppixdiff1) *ppixdiff1 = NULL;
1720 if (ppixdiff2) *ppixdiff2 = NULL;
1722 return ERROR_INT(
"&fract not defined", __func__, 1);
1724 if ((dilation & 1) == 0)
1725 return ERROR_INT(
"dilation must be odd", __func__, 1);
1727 return ERROR_INT(
"pixs1 not defined", __func__, 1);
1729 return ERROR_INT(
"pixs2 not defined", __func__, 1);
1730 d1 = pixGetDepth(pixs1);
1731 d2 = pixGetDepth(pixs2);
1732 if (!pixGetColormap(pixs1) && d1 < 8)
1733 return ERROR_INT(
"pixs1 not cmapped and < 8 bpp", __func__, 1);
1734 if (!pixGetColormap(pixs2) && d2 < 8)
1735 return ERROR_INT(
"pixs2 not cmapped and < 8 bpp", __func__, 1);
1739 pix1 = pixScaleByIntSampling(pixs1, sampling);
1740 pix2 = pixScaleByIntSampling(pixs2, sampling);
1742 pix1 = pixClone(pixs1);
1743 pix2 = pixClone(pixs2);
1747 if (pixGetColormap(pix1)) {
1749 d1 = pixGetDepth(pix3);
1751 pix3 = pixClone(pix1);
1753 if (pixGetColormap(pix2)) {
1755 d2 = pixGetDepth(pix4);
1757 pix4 = pixClone(pix2);
1761 if (d1 != d2 || (d1 != 8 && d1 != 32)) {
1764 L_INFO(
"depths unequal or not in {8,32}: d1 = %d, d2 = %d\n",
1778 pix5 = pixDilateGray(pix3, dilation, dilation);
1779 pixCompareGray(pix4, pix5, L_COMPARE_SUBTRACT, 0, NULL, NULL, NULL,
1781 pix6 = pixDilateGray(pix4, dilation, dilation);
1782 pixCompareGray(pix3, pix6, L_COMPARE_SUBTRACT, 0, NULL, NULL, NULL,
1784 pix9 = pixMinOrMax(NULL, pix7, pix8, L_CHOOSE_MAX);
1785 pix10 = pixThresholdToBinary(pix9, mindiff);
1786 pixInvert(pix10, pix10);
1787 pixCountPixels(pix10, &count, NULL);
1788 pixGetDimensions(pix10, &w, &h, NULL);
1789 *pfract = (w <= 0 || h <= 0) ? 0.0 :
1790 (l_float32)count / (l_float32)(w * h);
1804 pix5 = pixColorMorph(pix3, L_MORPH_DILATE, dilation, dilation);
1805 pixCompareRGB(pix4, pix5, L_COMPARE_SUBTRACT, 0, NULL, NULL, NULL,
1807 pix6 = pixColorMorph(pix4, L_MORPH_DILATE, dilation, dilation);
1808 pixCompareRGB(pix3, pix6, L_COMPARE_SUBTRACT, 0, NULL, NULL, NULL,
1810 pix9 = pixMinOrMax(NULL, pix7, pix8, L_CHOOSE_MAX);
1811 pix10 = pixConvertRGBToGrayMinMax(pix9, L_CHOOSE_MAX);
1812 pix11 = pixThresholdToBinary(pix10, mindiff);
1813 pixInvert(pix11, pix11);
1814 pixCountPixels(pix11, &count, NULL);
1815 pixGetDimensions(pix11, &w, &h, NULL);
1816 *pfract = (w <= 0 || h <= 0) ? 0.0 :
1817 (l_float32)count / (l_float32)(w * h);
1876l_int32 same, i, j, w, h, d, wpl1, wpl2, v1, v2, r1, g1, b1, r2, g2, b2;
1877l_uint32 *data1, *data2, *line1, *line2;
1881 return ERROR_INT(
"&psnr not defined", __func__, 1);
1884 return ERROR_INT(
"empty input pix", __func__, 1);
1885 if (!pixSizesEqual(pix1, pix2))
1886 return ERROR_INT(
"pix sizes unequal", __func__, 1);
1887 if (pixGetColormap(pix1))
1888 return ERROR_INT(
"pix1 has colormap", __func__, 1);
1889 if (pixGetColormap(pix2))
1890 return ERROR_INT(
"pix2 has colormap", __func__, 1);
1891 pixGetDimensions(pix1, &w, &h, &d);
1892 if (d != 8 && d != 32)
1893 return ERROR_INT(
"pix not 8 or 32 bpp", __func__, 1);
1895 return ERROR_INT(
"invalid sampling factor", __func__, 1);
1903 data1 = pixGetData(pix1);
1904 data2 = pixGetData(pix2);
1905 wpl1 = pixGetWpl(pix1);
1906 wpl2 = pixGetWpl(pix2);
1909 for (i = 0; i < h; i += factor) {
1910 line1 = data1 + i * wpl1;
1911 line2 = data2 + i * wpl2;
1912 for (j = 0; j < w; j += factor) {
1915 mse += (l_float32)(v1 - v2) * (v1 - v2);
1919 for (i = 0; i < h; i += factor) {
1920 line1 = data1 + i * wpl1;
1921 line2 = data2 + i * wpl2;
1922 for (j = 0; j < w; j += factor) {
1923 extractRGBValues(line1[j], &r1, &g1, &b1);
1924 extractRGBValues(line2[j], &r2, &g2, &b2);
1925 mse += ((l_float32)(r1 - r2) * (r1 - r2) +
1926 (g1 - g2) * (g1 - g2) +
1927 (b1 - b2) * (b1 - b2)) / 3.0;
1931 mse = mse / ((l_float32)(w) * h);
1933 *ppsnr = -4.3429448 * log(mse / (255 * 255));
1996 l_float32 textthresh,
1999 l_float32 simthresh,
2001 l_float32 **pscores,
2006l_int32 i, j, nim, w, h, w1, h1, w2, h2, ival, index, classid;
2009NUMA *nai, *naw, *nah;
2014 if (pscores) *pscores = NULL;
2015 if (ppixd) *ppixd = NULL;
2017 return ERROR_INT(
"&na not defined", __func__, 1);
2020 return ERROR_INT(
"pixa not defined", __func__, 1);
2021 if (minratio < 0.0 || minratio > 1.0)
2022 return ERROR_INT(
"minratio not in [0.0 ... 1.0]", __func__, 1);
2023 if (textthresh <= 0.0) textthresh = 1.3f;
2025 return ERROR_INT(
"subsampling factor must be >= 1", __func__, 1);
2026 if (n < 1 || n > 7) {
2027 L_WARNING(
"n = %d is invalid; setting to 4\n", __func__, n);
2030 if (simthresh <= 0.0) simthresh = 0.25;
2031 if (simthresh > 1.0)
2032 return ERROR_INT(
"simthresh invalid; should be near 0.25", __func__, 1);
2035 nim = pixaGetCount(pixa);
2036 if ((n3a = (
NUMAA **)LEPT_CALLOC(nim,
sizeof(
NUMAA *))) == NULL)
2037 return ERROR_INT(
"calloc fail for n3a", __func__, 1);
2038 naw = numaCreate(0);
2039 nah = numaCreate(0);
2040 for (i = 0; i < nim; i++) {
2041 pix = pixaGetPix(pixa, i,
L_CLONE);
2042 text = pixGetText(pix);
2043 pixSetResolution(pix, 150, 150);
2044 index = (debug) ? i : 0;
2046 &naa, &w, &h, index);
2048 numaAddNumber(naw, w);
2049 numaAddNumber(nah, h);
2051 lept_stderr(
"Image %s is photo\n", text);
2053 lept_stderr(
"Image %s is NOT photo\n", text);
2064 (l_float32 *)LEPT_CALLOC((
size_t)nim * nim,
sizeof(l_float32)))
2066 L_ERROR(
"calloc fail for scores\n", __func__);
2069 nai = numaMakeConstant(-1, nim);
2070 for (i = 0, classid = 0; i < nim; i++) {
2071 scores[nim * i + i] = 1.0;
2072 numaGetIValue(nai, i, &ival);
2075 numaSetValue(nai, i, classid);
2076 if (n3a[i] == NULL) {
2080 numaGetIValue(naw, i, &w1);
2081 numaGetIValue(nah, i, &h1);
2082 for (j = i + 1; j < nim; j++) {
2083 numaGetIValue(nai, j, &ival);
2088 numaGetIValue(naw, j, &w2);
2089 numaGetIValue(nah, j, &h2);
2092 scores[nim * i + j] = score;
2093 scores[nim * j + i] = score;
2095 if (score > simthresh) {
2096 numaSetValue(nai, j, classid);
2098 "Setting %d similar to %d, in class %d; score %5.3f\n",
2099 j, i, classid, score);
2114 l_uint32 *line, *data;
2116 pix2 = pixCreate(nim, nim, 8);
2117 data = pixGetData(pix2);
2118 wpl = pixGetWpl(pix2);
2119 for (i = 0; i < nim; i++) {
2120 line = data + i * wpl;
2121 for (j = 0; j < nim; j++) {
2123 L_MIN(255, 4.0 * 255 * scores[nim * i + j]));
2126 fact = L_MAX(2, 1000 / nim);
2127 pix3 = pixExpandReplicate(pix2, fact);
2128 lept_stderr(
"Writing to /tmp/lept/comp/scorearray.png\n");
2129 lept_mkdir(
"lept/comp");
2130 pixWrite(
"/tmp/lept/comp/scorearray.png", pix3, IFF_PNG);
2142 *ppixd = pixaDisplayTiledByIndex(pixa, nai, 200, 20, 2, 6, 0x0000ff00);
2147 for (i = 0; i < nim; i++)
2148 numaaDestroy(&n3a[i]);
2224l_int32 w1, h1, w2, h2, w1c, h1c, w2c, h2c, debugindex;
2225l_float32 wratio, hratio;
2231 return ERROR_INT(
"&score not defined", __func__, 1);
2234 return ERROR_INT(
"pix1 and pix2 not both defined", __func__, 1);
2235 if (minratio < 0.5 || minratio > 1.0)
2236 return ERROR_INT(
"minratio not in [0.5 ... 1.0]", __func__, 1);
2238 return ERROR_INT(
"subsampling factor must be >= 1", __func__, 1);
2239 if (n < 1 || n > 7) {
2240 L_WARNING(
"n = %d is invalid; setting to 4\n", __func__, n);
2246 lept_mkdir(
"lept/comp");
2252 boxGetGeometry(box1, NULL, NULL, &w1, &h1);
2254 pixGetDimensions(pix1, &w1, &h1, NULL);
2256 boxGetGeometry(box2, NULL, NULL, &w2, &h2);
2258 pixGetDimensions(pix1, &w2, &h2, NULL);
2259 wratio = (w1 < w2) ? (l_float32)w1 / (l_float32)w2 :
2260 (l_float32)w2 / (l_float32)w1;
2261 hratio = (h1 < h2) ? (l_float32)h1 / (l_float32)h2 :
2262 (l_float32)h2 / (l_float32)h1;
2263 if (wratio < minratio || hratio < minratio)
2268 pix3 = pixClipRectangle(pix1, box1, NULL);
2270 pix3 = pixClone(pix1);
2273 if (!naa1)
return 0;
2275 pix4 = pixClipRectangle(pix2, box2, NULL);
2277 pix4 = pixClone(pix2);
2280 if (!naa2)
return 0;
2283 pixa = (debugflag) ? pixaCreate(0) : NULL;
2341PIX *pix1, *pix2, *pix3, *pixm;
2344 if (pnaa) *pnaa = NULL;
2348 return ERROR_INT(
"&naa not defined", __func__, 1);
2350 return ERROR_INT(
"&w and &h not both defined", __func__, 1);
2351 if (!pixs || pixGetDepth(pixs) == 1)
2352 return ERROR_INT(
"pixs not defined or 1 bpp", __func__, 1);
2354 return ERROR_INT(
"subsampling factor must be >= 1", __func__, 1);
2355 if (thresh <= 0.0) thresh = 1.3f;
2356 if (n < 1 || n > 7) {
2357 L_WARNING(
"n = %d is invalid; setting to 4\n", __func__, n);
2362 if (debugindex > 0) {
2363 pixa = pixaCreate(0);
2364 lept_mkdir(
"lept/comp");
2369 pix1 = pixClipRectangle(pixs, box, NULL);
2371 pix1 = pixClone(pixs);
2374 pix2 = pixConvertTo8(pix1, FALSE);
2379 pixm = pixThresholdToBinary(pix3, 230);
2380 pixInvert(pixm, pixm);
2381 pixSetMaskedGeneral(pix3, pixm, 255, 0, 0);
2384 if (debugindex > 0) {
2385 PIX *pix4, *pix5, *pix6, *pix7, *pix8;
2387 pix4 = pixConvertTo32(pix2);
2388 pix5 = pixConvertTo32(pix3);
2389 pix6 = pixScaleToSize(pix4, 400, 0);
2390 pix7 = pixScaleToSize(pix5, 400, 0);
2391 pixa2 = pixaCreate(2);
2394 pix8 = pixaDisplayTiledInRows(pixa2, 32, 1000, 1.0, 0, 50, 3);
2398 pixaDestroy(&pixa2);
2407 *pw = pixGetWidth(pix3);
2408 *ph = pixGetHeight(pix3);
2412 snprintf(buf,
sizeof(buf),
"/tmp/lept/comp/tiledhistos.%d.pdf",
2414 lept_stderr(
"Writing to %s\n", buf);
2445l_int32 xs, ys, delx, dely, icx, icy, ws, hs, wd, hd;
2449 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
2451 return (
PIX *)ERROR_PTR(
"invalid sampling factor", __func__, NULL);
2453 pix1 = pixConvertTo8(pixs, FALSE);
2455 icx = (l_int32)(cx + 0.5);
2456 icy = (l_int32)(cy + 0.5);
2457 pixGetDimensions(pix1, &ws, &hs, NULL);
2458 delx = ws - 2 * icx;
2459 dely = hs - 2 * icy;
2460 xs = L_MAX(0, delx);
2461 ys = L_MAX(0, dely);
2462 wd = 2 * L_MAX(icx, ws - icx);
2463 hd = 2 * L_MAX(icy, hs - icy);
2464 pixd = pixCreate(wd, hd, 8);
2466 pixCopyResolution(pixd, pixs);
2467 pixRasterop(pixd, xs, ys, ws, hs,
PIX_SRC, pix1, 0, 0);
2497l_int32 i, j, w, h, wpl, val;
2498l_float32 sumx, sumy, sumv;
2499l_uint32 *data, *line;
2502 if (pcx) *pcx = 0.0;
2503 if (pcy) *pcy = 0.0;
2504 if (!pixs || pixGetDepth(pixs) != 8)
2505 return ERROR_INT(
"pixs undefined or not 8 bpp", __func__, 1);
2507 return ERROR_INT(
"subsampling factor must be >= 1", __func__, 1);
2509 return ERROR_INT(
"&cx and &cy not both defined", __func__, 1);
2511 pix1 = pixInvert(NULL, pixs);
2512 pixGetDimensions(pix1, &w, &h, NULL);
2513 data = pixGetData(pix1);
2514 wpl = pixGetWpl(pix1);
2515 sumx = sumy = sumv = 0.0;
2516 for (i = 0; i < h; i++) {
2517 line = data + i * wpl;
2518 for (j = 0; j < w; j++) {
2528 L_INFO(
"input image is white\n", __func__);
2529 *pcx = (l_float32)(w) / 2;
2530 *pcy = (l_float32)(h) / 2;
2584l_int32 i, w, h, nx, ny, ngrids, istext, isphoto;
2585l_float32 maxval, sum1, sum2, ratio;
2587NUMA *na1, *na2, *na3, *narv;
2590PIXA *pixa1, *pixa2, *pixa3;
2593 return ERROR_INT(
"&naa not defined", __func__, 1);
2595 if (!pix || pixGetDepth(pix) != 8 || pixGetColormap(pix))
2596 return ERROR_INT(
"pix undefined or invalid", __func__, 1);
2597 if (n < 1 || n > 7) {
2598 L_WARNING(
"n = %d is invalid; setting to 4\n", __func__, n);
2601 if (thresh <= 0.0) thresh = 1.3f;
2604 pixDecideIfText(pix, NULL, &istext, pixadebug);
2606 L_INFO(
"Image is text\n", __func__);
2611 pixGetDimensions(pix, &w, &h, NULL);
2612 if (w == 0 || h == 0)
2613 return ERROR_INT(
"invalid pix dimension", __func__, 1);
2617 pixa1 = pixaSplitPix(pix, nx, ny, 0, 0);
2619 bmf = (pixadebug) ? bmfCreate(NULL, 6) : NULL;
2620 naa = numaaCreate(ngrids);
2622 lept_rmdir(
"lept/compplot");
2623 lept_mkdir(
"lept/compplot");
2625 for (i = 0; i < ngrids; i++) {
2626 pix1 = pixaGetPix(pixa1, i,
L_CLONE);
2629 na1 = pixGetGrayHistogram(pix1, factor);
2630 numaSetValue(na1, 255, 0);
2631 na2 = numaWindowedMean(na1, 5);
2632 numaGetMax(na2, &maxval, NULL);
2633 na3 = numaTransform(na2, 0, 255.0 / maxval);
2635 snprintf(buf,
sizeof(buf),
"/tmp/lept/compplot/plot.%d", i);
2636 gplotSimple1(na3, GPLOT_PNG, buf,
"Histos");
2645 pix1 = pixaDisplayTiledInColumns(pixa1, nx, 1.0, 30, 2);
2646 pixaAddPix(pixadebug, pix1,
L_INSERT);
2647 pixa2 = pixaReadFiles(
"/tmp/lept/compplot",
".png");
2648 pixa3 = pixaScale(pixa2, 0.4f, 0.4f);
2649 pix1 = pixaDisplayTiledInColumns(pixa3, nx, 1.0, 30, 2);
2650 pixaAddPix(pixadebug, pix1,
L_INSERT);
2651 pixaDestroy(&pixa2);
2652 pixaDestroy(&pixa3);
2658 grayInterHistogramStats(naa, 5, NULL, NULL, NULL, &narv);
2665 numaGetSumOnInterval(narv, 50, 150, &sum1);
2666 numaGetSumOnInterval(narv, 200, 230, &sum2);
2671 ratio = sum1 / sum2;
2672 isphoto = (ratio > thresh) ? 1 : 0;
2676 L_INFO(
"ratio %f > %f; isphoto is true\n",
2677 __func__, ratio, thresh);
2679 L_INFO(
"ratio %f < %f; isphoto is false\n",
2680 __func__, ratio, thresh);
2688 pixaDestroy(&pixa1);
2729 ratio = (l_float32)w / (l_float32)h;
2732 while (nx > 1 && ny > 1) {
2737 lept_stderr(
"nx = %d, ny = %d, ratio w/h = %4.2f\n",
2739 }
else if (ratio < 0.5) {
2743 lept_stderr(
"nx = %d, ny = %d, ratio w/h = %4.2f\n",
2747 lept_stderr(
"nx = %d, ny = %d, ratio w/h = %4.2f\n",
2751 ratio = (l_float32)(ny * w) / (l_float32)(nx * h);
2792char buf1[128], buf2[128];
2794l_float32 wratio, hratio, score, minscore, dist;
2796NUMA *na1, *na2, *nadist, *nascore;
2799 return ERROR_INT(
"&score not defined", __func__, 1);
2802 return ERROR_INT(
"naa1 and naa2 not both defined", __func__, 1);
2805 wratio = (w1 < w2) ? (l_float32)w1 / (l_float32)w2 :
2806 (l_float32)w2 / (l_float32)w1;
2807 hratio = (h1 < h2) ? (l_float32)h1 / (l_float32)h2 :
2808 (l_float32)h2 / (l_float32)h1;
2809 if (wratio < minratio || hratio < minratio) {
2811 L_INFO(
"Sizes differ: wratio = %f, hratio = %f\n",
2812 __func__, wratio, hratio);
2815 n = numaaGetCount(naa1);
2816 if (n != numaaGetCount(naa2)) {
2817 L_INFO(
"naa1 and naa2 sizes are different\n", __func__);
2822 lept_rmdir(
"lept/comptile");
2823 lept_mkdir(
"lept/comptile");
2832 nadist = numaCreate(n);
2833 nascore = numaCreate(n);
2834 bmf = (pixadebug) ? bmfCreate(NULL, 6) : NULL;
2835 for (i = 0; i < n; i++) {
2836 na1 = numaaGetNuma(naa1, i,
L_CLONE);
2837 na2 = numaaGetNuma(naa2, i,
L_CLONE);
2838 numaSetValue(na1, 255, 0.0);
2839 numaSetValue(na2, 255, 0.0);
2845 numaEarthMoverDistance(na1, na2, &dist);
2846 score = L_MAX(0.0, 1.0 - 10.0 * (dist / 255.));
2847 numaAddNumber(nadist, dist);
2848 numaAddNumber(nascore, score);
2849 minscore = L_MIN(minscore, score);
2851 snprintf(buf1,
sizeof(buf1),
"/tmp/lept/comptile/plot.%d", i);
2852 gplotSimple2(na1, na2, GPLOT_PNG, buf1,
"Histos");
2860 for (i = 0; i < n; i++) {
2862 snprintf(buf1,
sizeof(buf1),
"/tmp/lept/comptile/plot.%d.png", i);
2863 pix1 = pixRead(buf1);
2864 numaGetFValue(nadist, i, &dist);
2865 numaGetFValue(nascore, i, &score);
2866 snprintf(buf2,
sizeof(buf2),
2867 "Image %d\ndist = %5.3f, score = %5.3f", i, dist, score);
2868 pix2 = pixAddTextlines(pix1, bmf, buf2, 0x0000ff00,
L_ADD_BELOW);
2869 pixaAddPix(pixadebug, pix2,
L_INSERT);
2872 lept_stderr(
"Writing to /tmp/lept/comptile/comparegray.pdf\n");
2874 "/tmp/lept/comptile/comparegray.pdf");
2875 numaWriteDebug(
"/tmp/lept/comptile/scores.na", nascore);
2876 numaWriteDebug(
"/tmp/lept/comptile/dists.na", nadist);
2880 numaDestroy(&nadist);
2881 numaDestroy(&nascore);
2969l_int32 w1, h1, w2, h2;
2970l_float32 wratio, hratio;
2972PIX *pix3, *pix4, *pix5, *pix6, *pix7, *pix8;
2976 return ERROR_INT(
"&score not defined", __func__, 1);
2979 return ERROR_INT(
"pix1 and pix2 not both defined", __func__, 1);
2980 if (minratio < 0.5 || minratio > 1.0)
2981 return ERROR_INT(
"minratio not in [0.5 ... 1.0]", __func__, 1);
2983 return ERROR_INT(
"invalid maxgray; should be >= 200", __func__, 1);
2984 maxgray = L_MIN(255, maxgray);
2986 return ERROR_INT(
"subsampling factor must be >= 1", __func__, 1);
2987 if (n < 1 || n > 7) {
2988 L_WARNING(
"n = %d is invalid; setting to 4\n", __func__, n);
2993 lept_mkdir(
"lept/comp");
2997 boxGetGeometry(box1, NULL, NULL, &w1, &h1);
2999 pixGetDimensions(pix1, &w1, &h1, NULL);
3001 boxGetGeometry(box2, NULL, NULL, &w2, &h2);
3003 pixGetDimensions(pix1, &w2, &h2, NULL);
3004 wratio = (w1 < w2) ? (l_float32)w1 / (l_float32)w2 :
3005 (l_float32)w2 / (l_float32)w1;
3006 hratio = (h1 < h2) ? (l_float32)h1 / (l_float32)h2 :
3007 (l_float32)h2 / (l_float32)h1;
3008 if (wratio < minratio || hratio < minratio)
3013 pix3 = pixClipRectangle(pix1, box1, NULL);
3015 pix3 = pixClone(pix1);
3017 pix4 = pixClipRectangle(pix2, box2, NULL);
3019 pix4 = pixClone(pix2);
3022 pix5 = pixConvertTo8(pix3, FALSE);
3023 pix6 = pixConvertTo8(pix4, FALSE);
3025 pix7 = pixClipRectangle(pix5, box3, NULL);
3026 pix8 = pixClipRectangle(pix6, box4, NULL);
3027 pixa = (debugflag) ? pixaCreate(0) : NULL;
3029 PIX *pix9, *pix10, *pix11, *pix12, *pix13;
3031 pix9 = pixConvertTo32(pix5);
3032 pix10 = pixConvertTo32(pix6);
3033 pixRenderBoxArb(pix9, box3, 2, 255, 0, 0);
3034 pixRenderBoxArb(pix10, box4, 2, 255, 0, 0);
3035 pix11 = pixScaleToSize(pix9, 400, 0);
3036 pix12 = pixScaleToSize(pix10, 400, 0);
3037 pixa2 = pixaCreate(2);
3038 pixaAddPix(pixa2, pix11,
L_INSERT);
3039 pixaAddPix(pixa2, pix12,
L_INSERT);
3040 pix13 = pixaDisplayTiledInRows(pixa2, 32, 1000, 1.0, 0, 50, 0);
3044 pixaDestroy(&pixa2);
3092l_int32 w, h, i, j, nx, ny, ngr;
3093l_float32 score, minscore, maxval1, maxval2, dist;
3095NUMA *na1, *na2, *na3, *na4, *na5, *na6, *na7;
3100 return ERROR_INT(
"&score not defined", __func__, 1);
3103 return ERROR_INT(
"pix1 and pix2 not both defined", __func__, 1);
3106 pixGetDimensions(pix1, &w, &h, NULL);
3111 pixa1 = pixaSplitPix(pix1, nx, ny, 0, 0);
3112 pixa2 = pixaSplitPix(pix2, nx, ny, 0, 0);
3113 na7 = (pixadebug) ? numaCreate(ngr) : NULL;
3114 bmf = (pixadebug) ? bmfCreate(NULL, 6) : NULL;
3116 for (i = 0; i < ngr; i++) {
3117 pix3 = pixaGetPix(pixa1, i,
L_CLONE);
3118 pix4 = pixaGetPix(pixa2, i,
L_CLONE);
3121 na1 = pixGetGrayHistogram(pix3, factor);
3122 na2 = pixGetGrayHistogram(pix4, factor);
3123 if (maxgray < 255) {
3124 for (j = maxgray + 1; j <= 255; j++) {
3125 numaSetValue(na1, j, 0);
3126 numaSetValue(na2, j, 0);
3129 na3 = numaWindowedMean(na1, 5);
3130 na4 = numaWindowedMean(na2, 5);
3131 numaGetMax(na3, &maxval1, NULL);
3132 numaGetMax(na4, &maxval2, NULL);
3133 na5 = numaTransform(na3, 0, 255.0 / maxval1);
3134 na6 = numaTransform(na4, 0, 255.0 / maxval2);
3136 gplotSimple2(na5, na6, GPLOT_PNG,
"/tmp/lept/comp/plot1",
"Histos");
3143 numaEarthMoverDistance(na5, na6, &dist);
3144 score = L_MAX(0.0, 1.0 - 8.0 * (dist / 255.));
3145 if (pixadebug) numaAddNumber(na7, score);
3146 minscore = L_MIN(minscore, score);
3148 PIX *pix5, *pix6, *pix7, *pix8, *pix9, *pix10;
3150 l_int32 w, h, wscale;
3151 pixa3 = pixaCreate(3);
3152 pixGetDimensions(pix3, &w, &h, NULL);
3153 wscale = (w > h) ? 700 : 400;
3154 pix5 = pixScaleToSize(pix3, wscale, 0);
3155 pix6 = pixScaleToSize(pix4, wscale, 0);
3158 pix7 = pixRead(
"/tmp/lept/comp/plot1.png");
3159 pix8 = pixScaleToSize(pix7, 700, 0);
3160 snprintf(buf,
sizeof(buf),
"%5.3f", score);
3161 pix9 = pixAddTextlines(pix8, bmf, buf, 0x0000ff00,
L_ADD_RIGHT);
3163 pix10 = pixaDisplayTiledInRows(pixa3, 32, 1000, 1.0, 0, 50, 0);
3164 pixaAddPix(pixadebug, pix10,
L_INSERT);
3167 pixaDestroy(&pixa3);
3182 "/tmp/lept/comp/comparegray.pdf");
3183 numaWriteDebug(
"/tmp/lept/comp/tilescores.na", na7);
3188 pixaDestroy(&pixa1);
3189 pixaDestroy(&pixa2);
3217l_float32 cx1, cy1, cx2, cy2;
3218l_int32 w1, h1, w2, h2, icx1, icy1, icx2, icy2;
3219l_int32 xm, xm1, xm2, xp, xp1, xp2, ym, ym1, ym2, yp, yp1, yp2;
3222 if (pbox1) *pbox1 = NULL;
3223 if (pbox2) *pbox2 = NULL;
3225 return ERROR_INT(
"pix1 and pix2 not both defined", __func__, 1);
3227 return ERROR_INT(
"subsampling factor must be >= 1", __func__, 1);
3228 if (!pbox1 || !pbox2)
3229 return ERROR_INT(
"&box1 and &box2 not both defined", __func__, 1);
3231 pix3 = pixConvertTo8(pix1, FALSE);
3232 pix4 = pixConvertTo8(pix2, FALSE);
3235 pixGetDimensions(pix3, &w1, &h1, NULL);
3236 pixGetDimensions(pix4, &w2, &h2, NULL);
3240 icx1 = (l_int32)(cx1 + 0.5);
3241 icy1 = (l_int32)(cy1 + 0.5);
3242 icx2 = (l_int32)(cx2 + 0.5);
3243 icy2 = (l_int32)(cy2 + 0.5);
3244 xm = L_MIN(icx1, icx2);
3247 xp = L_MIN(w1 - icx1, w2 - icx2);
3250 ym = L_MIN(icy1, icy2);
3253 yp = L_MIN(h1 - icy1, h2 - icy2);
3256 *pbox1 = boxCreate(xm1, ym1, xp1 - xm1, yp1 - ym1);
3257 *pbox2 = boxCreate(xm2, ym2, xp2 - xm2, yp2 - ym2);
3290l_int32 i, j, n, nn, ival;
3295 return (l_uint8 *)ERROR_PTR(
"&size not defined", __func__, NULL);
3298 return (l_uint8 *)ERROR_PTR(
"naa not defined", __func__, NULL);
3299 n = numaaGetCount(naa);
3300 for (i = 0; i < n; i++) {
3301 nn = numaaGetNumaCount(naa, i);
3303 L_ERROR(
"%d numbers in numa[%d]\n", __func__, nn, i);
3308 if ((bytea = (l_uint8 *)LEPT_CALLOC(8 + 256 * n,
sizeof(l_uint8))) == NULL)
3309 return (l_uint8 *)ERROR_PTR(
"bytea not made", __func__, NULL);
3310 *psize = 8 + 256 * n;
3311 l_setDataFourBytes(bytea, 0, w);
3312 l_setDataFourBytes(bytea, 1, h);
3313 for (i = 0; i < n; i++) {
3314 na1 = numaaGetNuma(naa, i,
L_COPY);
3315 numaGetMax(na1, &maxval, NULL);
3316 na2 = numaTransform(na1, 0, 255.0 / maxval);
3317 for (j = 0; j < 256; j++) {
3318 numaGetIValue(na2, j, &ival);
3319 bytea[8 + 256 * i + j] = ival;
3362 return (
NUMAA *)ERROR_PTR(
"&w and &h not both defined", __func__, NULL);
3364 return (
NUMAA *)ERROR_PTR(
"bytea not defined", __func__, NULL);
3365 n = (size - 8) / 256;
3366 if ((size - 8) % 256 != 0)
3367 return (
NUMAA *)ERROR_PTR(
"bytea size is invalid", __func__, NULL);
3369 *pw = l_getDataFourBytes(bytea, 0);
3370 *ph = l_getDataFourBytes(bytea, 1);
3371 naa = numaaCreate(n);
3372 for (i = 0; i < n; i++) {
3373 na = numaCreate(256);
3374 for (j = 0; j < 256; j++)
3375 numaAddNumber(na, bytea[8 + 256 * i + j]);
3426l_int32 i, level, area1, area2, delx, dely;
3427l_int32 etransx, etransy, maxshift, dbint;
3428l_int32 *stab, *ctab;
3429l_float32 cx1, cx2, cy1, cy2, score;
3430PIX *pixb1, *pixb2, *pixt1, *pixt2, *pixt3, *pixt4;
3431PIXA *pixa1, *pixa2, *pixadb = NULL;
3433 if (pdelx) *pdelx = 0;
3434 if (pdely) *pdely = 0;
3435 if (pscore) *pscore = 0.0;
3436 if (!pdelx || !pdely)
3437 return ERROR_INT(
"&delx and &dely not defined", __func__, 1);
3439 return ERROR_INT(
"&score not defined", __func__, 1);
3441 return ERROR_INT(
"pix1 not defined", __func__, 1);
3443 return ERROR_INT(
"pix2 not defined", __func__, 1);
3446 subtab = makeSubsampleTab2x();
3447 stab = makePixelSumTab8();
3448 ctab = makePixelCentroidTab8();
3451 pixb1 = pixConvertTo1(pix1, thresh);
3452 pixb2 = pixConvertTo1(pix2, thresh);
3456 pixa1 = pixaCreate(4);
3457 pixa2 = pixaCreate(4);
3459 pixadb = pixaCreate(4);
3460 pixaAddPix(pixa1, pixb1,
L_INSERT);
3461 pixaAddPix(pixa2, pixb2,
L_INSERT);
3462 for (i = 0; i < 3; i++) {
3463 pixt1 = pixReduceRankBinary2(pixb1, 2, subtab);
3464 pixt2 = pixReduceRankBinary2(pixb2, 2, subtab);
3465 pixaAddPix(pixa1, pixt1,
L_INSERT);
3466 pixaAddPix(pixa2, pixt2,
L_INSERT);
3475 for (level = 3; level >= 0; level--) {
3476 pixt1 = pixaGetPix(pixa1, level,
L_CLONE);
3477 pixt2 = pixaGetPix(pixa2, level,
L_CLONE);
3478 pixCountPixels(pixt1, &area1, stab);
3479 pixCountPixels(pixt2, &area2, stab);
3481 pixCentroid(pixt1, ctab, stab, &cx1, &cy1);
3482 pixCentroid(pixt2, ctab, stab, &cx2, &cy2);
3483 etransx = lept_roundftoi(cx1 - cx2);
3484 etransy = lept_roundftoi(cy1 - cy2);
3491 dbint = (debugflag) ? level + 1 : 0;
3493 maxshift, stab, &delx, &dely, &score, dbint);
3495 lept_stderr(
"Level %d: delx = %d, dely = %d, score = %7.4f\n",
3496 level, delx, dely, score);
3499 pixt4 = pixExpandReplicate(pixt3, 8 / (1 << (3 - level)));
3500 pixaAddPix(pixadb, pixt4,
L_INSERT);
3509 "/tmp/lept/comp/compare.pdf");
3510 convertFilesToPdf(
"/tmp/lept/comp",
"correl_", 30, 1.0,
L_FLATE_ENCODE,
3511 0,
"Correlation scores at levels 1 through 5",
3512 "/tmp/lept/comp/correl.pdf");
3513 pixaDestroy(&pixadb);
3519 pixaDestroy(&pixa1);
3520 pixaDestroy(&pixa2);
3582l_int32 shiftx, shifty, delx, dely;
3584l_float32 maxscore, score;
3588 if (pdelx) *pdelx = 0;
3589 if (pdely) *pdely = 0;
3590 if (pscore) *pscore = 0.0;
3591 if (!pix1 || pixGetDepth(pix1) != 1)
3592 return ERROR_INT(
"pix1 not defined or not 1 bpp", __func__, 1);
3593 if (!pix2 || pixGetDepth(pix2) != 1)
3594 return ERROR_INT(
"pix2 not defined or not 1 bpp", __func__, 1);
3595 if (!area1 || !area2)
3596 return ERROR_INT(
"areas must be > 0", __func__, 1);
3599 fpix = fpixCreate(2 * maxshift + 1, 2 * maxshift + 1);
3602 tab = makePixelSumTab8();
3610 for (shifty = -maxshift; shifty <= maxshift; shifty++) {
3611 for (shiftx = -maxshift; shiftx <= maxshift; shiftx++) {
3612 pixCorrelationScoreShifted(pix1, pix2, area1, area2,
3614 etransy + shifty, tab, &score);
3615 if (debugflag > 0) {
3616 fpixSetPixel(fpix, maxshift + shiftx, maxshift + shifty,
3621 if (score > maxscore) {
3623 delx = etransx + shiftx;
3624 dely = etransy + shifty;
3629 if (debugflag > 0) {
3631 lept_mkdir(
"lept/comp");
3632 pix3 = fpixDisplayMaxDynamicRange(fpix);
3633 pix4 = pixExpandReplicate(pix3, 20);
3634 snprintf(buf,
sizeof(buf),
"/tmp/lept/comp/correl_%d.png",
3636 pixWrite(buf, pix4, IFF_PNG);
3642 if (pdelx) *pdelx = delx;
3643 if (pdely) *pdely = dely;
3644 if (pscore) *pscore = maxscore;
3645 if (!tab8) LEPT_FREE(tab);
#define SET_DATA_FOUR_BYTES(pdata, n, val)
#define GET_DATA_BYTE(pdata, n)
#define GET_DATA_FOUR_BYTES(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
l_ok pixCompareGrayOrRGB(PIX *pix1, PIX *pix2, l_int32 comptype, l_int32 plottype, l_int32 *psame, l_float32 *pdiff, l_float32 *prmsdiff, PIX **ppixdiff)
pixCompareGrayOrRGB()
l_ok compareTilesByHisto(NUMAA *naa1, NUMAA *naa2, l_float32 minratio, l_int32 w1, l_int32 h1, l_int32 w2, l_int32 h2, l_float32 *pscore, PIXA *pixadebug)
compareTilesByHisto()
l_ok pixaComparePhotoRegionsByHisto(PIXA *pixa, l_float32 minratio, l_float32 textthresh, l_int32 factor, l_int32 n, l_float32 simthresh, NUMA **pnai, l_float32 **pscores, PIX **ppixd, l_int32 debug)
pixaComparePhotoRegionsByHisto()
PIX * pixDisplayDiff(PIX *pix1, PIX *pix2, l_int32 showall, l_int32 mindiff, l_uint32 diffcolor)
pixDisplayDiff()
l_ok pixGetDifferenceStats(PIX *pix1, PIX *pix2, l_int32 factor, l_int32 mindiff, l_float32 *pfractdiff, l_float32 *pavediff, l_int32 details)
pixGetDifferenceStats()
l_ok pixCropAlignedToCentroid(PIX *pix1, PIX *pix2, l_int32 factor, BOX **pbox1, BOX **pbox2)
pixCropAlignedToCentroid()
l_ok pixCompareGrayByHisto(PIX *pix1, PIX *pix2, BOX *box1, BOX *box2, l_float32 minratio, l_int32 maxgray, l_int32 factor, l_int32 n, l_float32 *pscore, l_int32 debugflag)
pixCompareGrayByHisto()
l_ok pixDecideIfPhotoImage(PIX *pix, l_int32 factor, l_float32 thresh, l_int32 n, NUMAA **pnaa, PIXA *pixadebug)
pixDecideIfPhotoImage()
PIX * pixDisplayDiffBinary(PIX *pix1, PIX *pix2)
pixDisplayDiffBinary()
l_ok pixCompareRGB(PIX *pix1, PIX *pix2, l_int32 comptype, l_int32 plottype, l_int32 *psame, l_float32 *pdiff, l_float32 *prmsdiff, PIX **ppixdiff)
pixCompareRGB()
l_ok pixGenPhotoHistos(PIX *pixs, BOX *box, l_int32 factor, l_float32 thresh, l_int32 n, NUMAA **pnaa, l_int32 *pw, l_int32 *ph, l_int32 debugindex)
pixGenPhotoHistos()
l_ok pixGetPSNR(PIX *pix1, PIX *pix2, l_int32 factor, l_float32 *ppsnr)
pixGetPSNR()
l_ok pixBestCorrelation(PIX *pix1, PIX *pix2, l_int32 area1, l_int32 area2, l_int32 etransx, l_int32 etransy, l_int32 maxshift, l_int32 *tab8, l_int32 *pdelx, l_int32 *pdely, l_float32 *pscore, l_int32 debugflag)
pixBestCorrelation()
l_ok cmapEqual(PIXCMAP *cmap1, PIXCMAP *cmap2, l_int32 ncomps, l_int32 *psame)
cmapEqual()
NUMA * pixGetDifferenceHistogram(PIX *pix1, PIX *pix2, l_int32 factor)
pixGetDifferenceHistogram()
static l_ok pixCompareTilesByHisto(PIX *pix1, PIX *pix2, l_int32 maxgray, l_int32 factor, l_int32 n, l_float32 *pscore, PIXA *pixadebug)
pixCompareTilesByHisto()
l_ok pixCompareWithTranslation(PIX *pix1, PIX *pix2, l_int32 thresh, l_int32 *pdelx, l_int32 *pdely, l_float32 *pscore, l_int32 debugflag)
pixCompareWithTranslation()
l_uint8 * l_compressGrayHistograms(NUMAA *naa, l_int32 w, l_int32 h, size_t *psize)
l_compressGrayHistograms()
l_ok pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqual()
PIX * pixPadToCenterCentroid(PIX *pixs, l_int32 factor)
pixPadToCenterCentroid()
l_ok pixComparePhotoRegionsByHisto(PIX *pix1, PIX *pix2, BOX *box1, BOX *box2, l_float32 minratio, l_int32 factor, l_int32 n, l_float32 *pscore, l_int32 debugflag)
pixComparePhotoRegionsByHisto()
l_ok pixEqualWithCmap(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqualWithCmap()
l_ok pixCompareGray(PIX *pix1, PIX *pix2, l_int32 comptype, l_int32 plottype, l_int32 *psame, l_float32 *pdiff, l_float32 *prmsdiff, PIX **ppixdiff)
pixCompareGray()
l_ok pixTestForSimilarity(PIX *pix1, PIX *pix2, l_int32 factor, l_int32 mindiff, l_float32 maxfract, l_float32 maxave, l_int32 *psimilar, l_int32 details)
pixTestForSimilarity()
NUMA * pixCompareRankDifference(PIX *pix1, PIX *pix2, l_int32 factor)
pixCompareRankDifference()
l_ok pixCorrelationBinary(PIX *pix1, PIX *pix2, l_float32 *pval)
pixCorrelationBinary()
l_ok pixCompareTiled(PIX *pix1, PIX *pix2, l_int32 sx, l_int32 sy, l_int32 type, PIX **ppixdiff)
pixCompareTiled()
l_ok pixCompareBinary(PIX *pix1, PIX *pix2, l_int32 comptype, l_float32 *pfract, PIX **ppixdiff)
pixCompareBinary()
l_ok pixUsesCmapColor(PIX *pixs, l_int32 *pcolor)
pixUsesCmapColor()
static l_ok findHistoGridDimensions(l_int32 n, l_int32 w, l_int32 h, l_int32 *pnx, l_int32 *pny, l_int32 debug)
findHistoGridDimensions()
l_ok pixGetPerceptualDiff(PIX *pixs1, PIX *pixs2, l_int32 sampling, l_int32 dilation, l_int32 mindiff, l_float32 *pfract, PIX **ppixdiff1, PIX **ppixdiff2)
pixGetPerceptualDiff()
NUMAA * l_uncompressGrayHistograms(l_uint8 *bytea, size_t size, l_int32 *pw, l_int32 *ph)
l_uncompressGrayHistograms()
l_ok pixCentroid8(PIX *pixs, l_int32 factor, l_float32 *pcx, l_float32 *pcy)
pixCentroid8()
l_ok pixEqualWithAlpha(PIX *pix1, PIX *pix2, l_int32 use_alpha, l_int32 *psame)
pixEqualWithAlpha()
@ REMOVE_CMAP_TO_FULL_COLOR
@ REMOVE_CMAP_TO_GRAYSCALE
@ REMOVE_CMAP_BASED_ON_SRC