blob: 01a479ab7911a19be832dbb6b76efd785433634b [file] [log] [blame] [edit]
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
- This software is distributed in the hope that it will be
- useful, but with NO WARRANTY OF ANY KIND.
- No author or distributor accepts responsibility to anyone for the
- consequences of using this software, or for whether it serves any
- particular purpose or works at all, unless he or she says so in
- writing. Everyone is granted permission to copy, modify and
- redistribute this source code, for commercial or non-commercial
- purposes, with the following restrictions: (1) the origin of this
- source code must not be misrepresented; (2) modified versions must
- be plainly marked as such; and (3) this notice may not be removed
- or altered from any source or modified source distribution.
*====================================================================*/
/*
* correlscore.c
*
* These are functions for computing correlation between
* pairs of 1 bpp images.
*
* l_float32 pixCorrelationScore()
* l_int32 pixCorrelationScoreThresholded()
* l_float32 pixCorrelationScoreSimple()
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "allheaders.h"
/*!
* pixCorrelationScore()
*
* Input: pix1 (test pix, 1 bpp)
* pix2 (exemplar pix, 1 bpp)
* area1 (number of on pixels in pix1)
* area2 (number of on pixels in pix2)
* delx (x comp of centroid difference)
* dely (y comp of centroid difference)
* maxdiffw (max width difference of pix1 and pix2)
* maxdiffh (max height difference of pix1 and pix2)
* tab (sum tab for byte)
* Return: correlation score
*
* Note: we check first that the two pix are roughly the same size.
* For jbclass (jbig2) applications at roughly 300 ppi, maxdiffw and
* maxdiffh should be at least 2.
*
* Only if they meet that criterion do we compare the bitmaps.
* The centroid difference is used to align the two images to the
* nearest integer for the correlation.
*
* The correlation score is the ratio of the square of the number of
* pixels in the AND of the two bitmaps to the product of the number
* of ON pixels in each. Denote the number of ON pixels in pix1
* by |1|, the number in pix2 by |2|, and the number in the AND
* of pix1 and pix2 by |1 & 2|. The correlation score is then
* (|1 & 2|)**2 / (|1|*|2|).
*
* This score is compared with an input threshold, which can
* be modified depending on the weight of the template.
* The modified threshold is
* thresh + (1.0 - thresh) * weight * R
* where
* weight is a fixed input factor between 0.0 and 1.0
* R = |2| / area(2)
* and area(2) is the total number of pixels in 2 (i.e., width x height).
*
* To understand why a weight factor is useful, consider what happens
* with thick, sans-serif characters that look similar and have a value
* of R near 1. Different characters can have a high correlation value,
* and the classifier will make incorrect substitutions. The weight
* factor raises the threshold for these characters.
*
* Yet another approach to reduce such substitutions is to run the classifier
* in a non-greedy way, matching to the template with the highest
* score, not the first template with a score satisfying the matching
* constraint. However, this is not particularly effective.
*
* The implementation here gives the same result as in
* pixCorrelationScoreSimple(), where a temporary Pix is made to hold
* the AND and implementation uses rasterop:
* pixt = pixCreateTemplate(pix1);
* pixRasterop(pixt, idelx, idely, wt, ht, PIX_SRC, pix2, 0, 0);
* pixRasterop(pixt, 0, 0, wi, hi, PIX_SRC & PIX_DST, pix1, 0, 0);
* pixCountPixels(pixt, &count, tab);
* pixDestroy(&pixt);
* However, here it is done in a streaming fashion, counting as it goes,
* and touching memory exactly once, giving a 3-4x speedup over the
* simple implementation. This very fast correlation matcher was
* contributed by William Rucklidge.
*/
l_float32
pixCorrelationScore(PIX *pix1,
PIX *pix2,
l_int32 area1,
l_int32 area2,
l_float32 delx, /* x(1) - x(3) */
l_float32 dely, /* y(1) - y(3) */
l_int32 maxdiffw,
l_int32 maxdiffh,
l_int32 *tab)
{
l_int32 wi, hi, wt, ht, delw, delh, idelx, idely, count;
l_int32 wpl1, wpl2, lorow, hirow, locol, hicol;
l_int32 x, y, pix1lskip, pix2lskip, rowwords1, rowwords2;
l_uint32 word1, word2, andw;
l_uint32 *row1, *row2;
l_float32 score;
PROCNAME("pixCorrelationScore");
if (!pix1 || pixGetDepth(pix1) != 1)
return (l_float32)ERROR_FLOAT("pix1 not 1 bpp", procName, 0.0);
if (!pix2 || pixGetDepth(pix2) != 1)
return (l_float32)ERROR_FLOAT("pix2 not 1 bpp", procName, 0.0);
if (!tab)
return (l_float32)ERROR_FLOAT("tab not defined", procName, 0.0);
if (area1 <= 0 || area2 <= 0)
return (l_float32)ERROR_FLOAT("areas must be > 0", procName, 0.0);
/* Eliminate based on size difference */
pixGetDimensions(pix1, &wi, &hi, NULL);
pixGetDimensions(pix2, &wt, &ht, NULL);
delw = L_ABS(wi - wt);
if (delw > maxdiffw)
return 0.0;
delh = L_ABS(hi - ht);
if (delh > maxdiffh)
return 0.0;
/* Round difference to nearest integer */
if (delx >= 0)
idelx = (l_int32)(delx + 0.5);
else
idelx = (l_int32)(delx - 0.5);
if (dely >= 0)
idely = (l_int32)(dely + 0.5);
else
idely = (l_int32)(dely - 0.5);
count = 0;
wpl1 = pixGetWpl(pix1);
wpl2 = pixGetWpl(pix2);
rowwords2 = wpl2;
/* What rows of pix1 need to be considered? Only those underlying the
* shifted pix2. */
lorow = L_MAX(idely, 0);
hirow = L_MIN(ht + idely, hi);
/* Get the pointer to the first row of each image that will be
* considered. */
row1 = pixGetData(pix1) + wpl1 * lorow;
row2 = pixGetData(pix2) + wpl2 * (lorow - idely);
/* Similarly, figure out which columns of pix1 will be considered. */
locol = L_MAX(idelx, 0);
hicol = L_MIN(wt + idelx, wi);
if (idelx >= 32) {
/* pix2 is shifted far enough to the right that pix1's first
* word(s) won't contribute to the count. Increment its
* pointer to point to the first word that will contribute,
* and adjust other values accordingly. */
pix1lskip = idelx >> 5; /* # of words to skip on left */
row1 += pix1lskip;
locol -= pix1lskip << 5;
hicol -= pix1lskip << 5;
idelx &= 31;
} else if (idelx <= -32) {
/* pix2 is shifted far enough to the left that its first word(s)
* won't contribute to the count. Increment its pointer
* to point to the first word that will contribute,
* and adjust other values accordingly. */
pix2lskip = -((idelx + 31) >> 5); /* # of words to skip on left */
row2 += pix2lskip;
rowwords2 -= pix2lskip;
idelx += pix2lskip << 5;
}
if ((locol >= hicol) || (lorow >= hirow)) { /* there is no overlap */
count = 0;
} else {
/* How many words of each row of pix1 need to be considered? */
rowwords1 = (hicol + 31) >> 5;
if (idelx == 0) {
/* There's no lateral offset; simple case. */
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
for (x = 0; x < rowwords1; x++) {
andw = row1[x] & row2[x];
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
}
} else if (idelx > 0) {
/* pix2 is shifted to the right. word 0 of pix1 is touched by
* word 0 of pix2; word 1 of pix1 is touched by word 0 and word
* 1 of pix2, and so on up to the last word of pix1 (word N),
* which is touched by words N-1 and N of pix1... if there is a
* word N. Handle the two cases (pix2 has N-1 words and pix2
* has at least N words) separately.
*
* Note: we know that pix2 has at least N-1 words (i.e.,
* rowwords2 >= rowwords1 - 1) by the following logic.
* We can pretend that idelx <= 31 because the >= 32 logic
* above adjusted everything appropriately. Then
* hicol <= wt + idelx <= wt + 31, so
* hicol + 31 <= wt + 62
* rowwords1 = (hicol + 31) >> 5 <= (wt + 62) >> 5
* rowwords2 == (wt + 31) >> 5, so
* rowwords1 <= rowwords2 + 1 */
if (rowwords2 < rowwords1) {
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
/* Do the first iteration so the loop can be
* branch-free. */
word1 = row1[0];
word2 = row2[0] >> idelx;
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
for (x = 1; x < rowwords2; x++) {
word1 = row1[x];
word2 = (row2[x] >> idelx) |
(row2[x - 1] << (32 - idelx));
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
/* Now the last iteration - we know that this is safe
* (i.e. rowwords1 >= 2) because rowwords1 > rowwords2
* > 0 (if it was 0, we'd have taken the "count = 0"
* fast-path out of here). */
word1 = row1[x];
word2 = row2[x - 1] << (32 - idelx);
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
} else {
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
/* Do the first iteration so the loop can be
* branch-free. This section is the same as above
* except for the different limit on the loop, since
* the last iteration is the same as all the other
* iterations (beyond the first). */
word1 = row1[0];
word2 = row2[0] >> idelx;
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
for (x = 1; x < rowwords1; x++) {
word1 = row1[x];
word2 = (row2[x] >> idelx) |
(row2[x - 1] << (32 - idelx));
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
}
}
} else {
/* pix2 is shifted to the left. word 0 of pix1 is touched by
* word 0 and word 1 of pix2, and so on up to the last word of
* pix1 (word N), which is touched by words N and N+1 of
* pix2... if there is a word N+1. Handle the two cases (pix2
* has N words and pix2 has at least N+1 words) separately. */
if (rowwords1 < rowwords2) {
/* pix2 has at least N+1 words, so every iteration through
* the loop can be the same. */
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
for (x = 0; x < rowwords1; x++) {
word1 = row1[x];
word2 = row2[x] << -idelx;
word2 |= row2[x + 1] >> (32 + idelx);
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
}
} else {
/* pix2 has only N words, so the last iteration is broken
* out. */
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
for (x = 0; x < rowwords1 - 1; x++) {
word1 = row1[x];
word2 = row2[x] << -idelx;
word2 |= row2[x + 1] >> (32 + idelx);
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
word1 = row1[x];
word2 = row2[x] << -idelx;
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
}
}
}
score = (l_float32)(count * count) / (l_float32)(area1 * area2);
/* fprintf(stderr, "score = %7.3f, count = %d, area1 = %d, area2 = %d\n",
score, count, area1, area2); */
return score;
}
/*!
* pixCorrelationScoreThresholded()
*
* Input: pix1 (test pix, 1 bpp)
* pix2 (exemplar pix, 1 bpp)
* area1 (number of on pixels in pix1)
* area2 (number of on pixels in pix2)
* delx (x comp of centroid difference)
* dely (y comp of centroid difference)
* maxdiffw (max width difference of pix1 and pix2)
* maxdiffh (max height difference of pix1 and pix2)
* tab (sum tab for byte)
* downcount (count of 1 pixels below each row of pix1)
* score_threshold
* Return: whether the correlation score is >= score_threshold
*
*
* Note: we check first that the two pix are roughly the same size.
* Only if they meet that criterion do we compare the bitmaps.
* The centroid difference is used to align the two images to the
* nearest integer for the correlation.
*
* The correlation score is the ratio of the square of the number of
* pixels in the AND of the two bitmaps to the product of the number
* of ON pixels in each. Denote the number of ON pixels in pix1
* by |1|, the number in pix2 by |2|, and the number in the AND
* of pix1 and pix2 by |1 & 2|. The correlation score is then
* (|1 & 2|)**2 / (|1|*|2|).
*
* This score is compared with an input threshold, which can
* be modified depending on the weight of the template.
* The modified threshold is
* thresh + (1.0 - thresh) * weight * R
* where
* weight is a fixed input factor between 0.0 and 1.0
* R = |2| / area(2)
* and area(2) is the total number of pixels in 2 (i.e., width x height).
*
* To understand why a weight factor is useful, consider what happens
* with thick, sans-serif characters that look similar and have a value
* of R near 1. Different characters can have a high correlation value,
* and the classifier will make incorrect substitutions. The weight
* factor raises the threshold for these characters.
*
* Yet another approach to reduce such substitutions is to run the classifier
* in a non-greedy way, matching to the template with the highest
* score, not the first template with a score satisfying the matching
* constraint. However, this is not particularly effective.
*
* This very fast correlation matcher was contributed by William Rucklidge.
*/
l_int32
pixCorrelationScoreThresholded(PIX *pix1,
PIX *pix2,
l_int32 area1,
l_int32 area2,
l_float32 delx, /* x(1) - x(3) */
l_float32 dely, /* y(1) - y(3) */
l_int32 maxdiffw,
l_int32 maxdiffh,
l_int32 *tab,
l_int32 *downcount,
l_float32 score_threshold)
{
l_int32 wi, hi, wt, ht, delw, delh, idelx, idely, count;
l_int32 wpl1, wpl2, lorow, hirow, locol, hicol, untouchable;
l_int32 x, y, pix1lskip, pix2lskip, rowwords1, rowwords2;
l_uint32 word1, word2, andw;
l_uint32 *row1, *row2;
l_float32 score;
l_int32 threshold;
PROCNAME("pixCorrelationScoreThresholded");
if (!pix1 || pixGetDepth(pix1) != 1)
return ERROR_INT("pix1 not 1 bpp", procName, 0);
if (!pix2 || pixGetDepth(pix2) != 1)
return ERROR_INT("pix2 not 1 bpp", procName, 0);
if (!tab)
return ERROR_INT("tab not defined", procName, 0);
if (area1 <= 0 || area2 <= 0)
return ERROR_INT("areas must be > 0", procName, 0);
/* Eliminate based on size difference */
pixGetDimensions(pix1, &wi, &hi, NULL);
pixGetDimensions(pix2, &wt, &ht, NULL);
delw = L_ABS(wi - wt);
if (delw > maxdiffw)
return FALSE;
delh = L_ABS(hi - ht);
if (delh > maxdiffh)
return FALSE;
/* Round difference to nearest integer */
if (delx >= 0)
idelx = (l_int32)(delx + 0.5);
else
idelx = (l_int32)(delx - 0.5);
if (dely >= 0)
idely = (l_int32)(dely + 0.5);
else
idely = (l_int32)(dely - 0.5);
/* Compute the correlation count that is needed so that
* count * count / (area1 * area2) >= score_threshold */
threshold = (l_int32)ceil(sqrt(score_threshold * area1 * area2));
count = 0;
wpl1 = pixGetWpl(pix1);
wpl2 = pixGetWpl(pix2);
rowwords2 = wpl2;
/* What rows of pix1 need to be considered? Only those underlying the
* shifted pix2. */
lorow = L_MAX(idely, 0);
hirow = L_MIN(ht + idely, hi);
/* Get the pointer to the first row of each image that will be
* considered. */
row1 = pixGetData(pix1) + wpl1 * lorow;
row2 = pixGetData(pix2) + wpl2 * (lorow - idely);
if (hirow <= hi) {
/* Some rows of pix1 will never contribute to count */
untouchable = downcount[hirow - 1];
}
/* Similarly, figure out which columns of pix1 will be considered. */
locol = L_MAX(idelx, 0);
hicol = L_MIN(wt + idelx, wi);
if (idelx >= 32) {
/* pix2 is shifted far enough to the right that pix1's first
* word(s) won't contribute to the count. Increment its
* pointer to point to the first word that will contribute,
* and adjust other values accordingly. */
pix1lskip = idelx >> 5; /* # of words to skip on left */
row1 += pix1lskip;
locol -= pix1lskip << 5;
hicol -= pix1lskip << 5;
idelx &= 31;
} else if (idelx <= -32) {
/* pix2 is shifted far enough to the left that its first word(s)
* won't contribute to the count. Increment its pointer
* to point to the first word that will contribute,
* and adjust other values accordingly. */
pix2lskip = -((idelx + 31) >> 5); /* # of words to skip on left */
row2 += pix2lskip;
rowwords2 -= pix2lskip;
idelx += pix2lskip << 5;
}
if ((locol >= hicol) || (lorow >= hirow)) { /* there is no overlap */
count = 0;
} else {
/* How many words of each row of pix1 need to be considered? */
rowwords1 = (hicol + 31) >> 5;
if (idelx == 0) {
/* There's no lateral offset; simple case. */
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
for (x = 0; x < rowwords1; x++) {
andw = row1[x] & row2[x];
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
/* If the count is over the threshold, no need to
* calculate any futher. Likewise, return early if the
* count plus the maximum count attainable from further
* rows is below the threshold. */
if (count >= threshold) return TRUE;
if (count + downcount[y] - untouchable < threshold) {
return FALSE;
}
}
} else if (idelx > 0) {
/* pix2 is shifted to the right. word 0 of pix1 is touched by
* word 0 of pix2; word 1 of pix1 is touched by word 0 and word
* 1 of pix2, and so on up to the last word of pix1 (word N),
* which is touched by words N-1 and N of pix1... if there is a
* word N. Handle the two cases (pix2 has N-1 words and pix2
* has at least N words) separately.
*
* Note: we know that pix2 has at least N-1 words (i.e.,
* rowwords2 >= rowwords1 - 1) by the following logic.
* We can pretend that idelx <= 31 because the >= 32 logic
* above adjusted everything appropriately. Then
* hicol <= wt + idelx <= wt + 31, so
* hicol + 31 <= wt + 62
* rowwords1 = (hicol + 31) >> 5 <= (wt + 62) >> 5
* rowwords2 == (wt + 31) >> 5, so
* rowwords1 <= rowwords2 + 1 */
if (rowwords2 < rowwords1) {
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
/* Do the first iteration so the loop can be
* branch-free. */
word1 = row1[0];
word2 = row2[0] >> idelx;
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
for (x = 1; x < rowwords2; x++) {
word1 = row1[x];
word2 = (row2[x] >> idelx) |
(row2[x - 1] << (32 - idelx));
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
/* Now the last iteration - we know that this is safe
* (i.e. rowwords1 >= 2) because rowwords1 > rowwords2
* > 0 (if it was 0, we'd have taken the "count = 0"
* fast-path out of here). */
word1 = row1[x];
word2 = row2[x - 1] << (32 - idelx);
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
if (count >= threshold) return TRUE;
if (count + downcount[y] - untouchable < threshold) {
return FALSE;
}
}
} else {
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
/* Do the first iteration so the loop can be
* branch-free. This section is the same as above
* except for the different limit on the loop, since
* the last iteration is the same as all the other
* iterations (beyond the first). */
word1 = row1[0];
word2 = row2[0] >> idelx;
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
for (x = 1; x < rowwords1; x++) {
word1 = row1[x];
word2 = (row2[x] >> idelx) |
(row2[x - 1] << (32 - idelx));
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
if (count >= threshold) return TRUE;
if (count + downcount[y] - untouchable < threshold) {
return FALSE;
}
}
}
} else {
/* pix2 is shifted to the left. word 0 of pix1 is touched by
* word 0 and word 1 of pix2, and so on up to the last word of
* pix1 (word N), which is touched by words N and N+1 of
* pix2... if there is a word N+1. Handle the two cases (pix2
* has N words and pix2 has at least N+1 words) separately. */
if (rowwords1 < rowwords2) {
/* pix2 has at least N+1 words, so every iteration through
* the loop can be the same. */
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
for (x = 0; x < rowwords1; x++) {
word1 = row1[x];
word2 = row2[x] << -idelx;
word2 |= row2[x + 1] >> (32 + idelx);
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
if (count >= threshold) return TRUE;
if (count + downcount[y] - untouchable < threshold) {
return FALSE;
}
}
} else {
/* pix2 has only N words, so the last iteration is broken
* out. */
for (y = lorow; y < hirow; y++, row1 += wpl1, row2 += wpl2) {
for (x = 0; x < rowwords1 - 1; x++) {
word1 = row1[x];
word2 = row2[x] << -idelx;
word2 |= row2[x + 1] >> (32 + idelx);
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
}
word1 = row1[x];
word2 = row2[x] << -idelx;
andw = word1 & word2;
count += tab[andw & 0xff] +
tab[(andw >> 8) & 0xff] +
tab[(andw >> 16) & 0xff] +
tab[andw >> 24];
if (count >= threshold) return TRUE;
if (count + downcount[y] - untouchable < threshold) {
return FALSE;
}
}
}
}
}
score = (l_float32)(count * count) / (l_float32)(area1 * area2);
if (score >= score_threshold) {
fprintf(stderr, "count %d < threshold %d but score %g >= score_threshold %g\n",
count, threshold, score, score_threshold);
}
return FALSE;
}
/*!
* pixCorrelationScoreSimple()
*
* Input: pix1 (test pix, 1 bpp)
* pix2 (exemplar pix, 1 bpp)
* area1 (number of on pixels in pix1)
* area2 (number of on pixels in pix2)
* delx (x comp of centroid difference)
* dely (y comp of centroid difference)
* maxdiffw (max width difference of pix1 and pix2)
* maxdiffh (max height difference of pix1 and pix2)
* tab (sum tab for byte)
* Return: correlation score
*
* Notes:
* (1) This calculates exactly the same value as pixCorrelationScore().
* It is 2-3x slower, but much simpler to understand.
*/
l_float32
pixCorrelationScoreSimple(PIX *pix1,
PIX *pix2,
l_int32 area1,
l_int32 area2,
l_float32 delx, /* x(1) - x(3) */
l_float32 dely, /* y(1) - y(3) */
l_int32 maxdiffw,
l_int32 maxdiffh,
l_int32 *tab)
{
l_int32 wi, hi, wt, ht, delw, delh, idelx, idely, count;
l_float32 score;
PIX *pixt;
PROCNAME("pixCorrelationScoreSimple");
if (!pix1 || pixGetDepth(pix1) != 1)
return (l_float32)ERROR_FLOAT("pix1 not 1 bpp", procName, 0.0);
if (!pix2 || pixGetDepth(pix2) != 1)
return (l_float32)ERROR_FLOAT("pix2 not 1 bpp", procName, 0.0);
if (!tab)
return (l_float32)ERROR_FLOAT("tab not defined", procName, 0.0);
if (!area1 || !area2)
return (l_float32)ERROR_FLOAT("areas must be > 0", procName, 0.0);
/* Eliminate based on size difference */
pixGetDimensions(pix1, &wi, &hi, NULL);
pixGetDimensions(pix2, &wt, &ht, NULL);
delw = L_ABS(wi - wt);
if (delw > maxdiffw)
return 0.0;
delh = L_ABS(hi - ht);
if (delh > maxdiffh)
return 0.0;
/* Round difference to nearest integer */
if (delx >= 0)
idelx = (l_int32)(delx + 0.5);
else
idelx = (l_int32)(delx - 0.5);
if (dely >= 0)
idely = (l_int32)(dely + 0.5);
else
idely = (l_int32)(dely - 0.5);
/* pixt = pixAnd(NULL, pix1, pix2), including shift.
* To insure that pixels are ON only within the
* intersection of pix1 and the shifted pix2:
* (1) Start with pixt cleared and equal in size to pix1.
* (2) Blit the shifted pix2 onto pixt. Then all ON pixels
* are within the intersection of pix1 and the shifted pix2.
* (3) AND pix1 with pixt. */
pixt = pixCreateTemplate(pix1);
pixRasterop(pixt, idelx, idely, wt, ht, PIX_SRC, pix2, 0, 0);
pixRasterop(pixt, 0, 0, wi, hi, PIX_SRC & PIX_DST, pix1, 0, 0);
pixCountPixels(pixt, &count, tab);
pixDestroy(&pixt);
score = (l_float32)(count * count) / (l_float32)(area1 * area2);
/* fprintf(stderr, "score = %7.3f, count = %d, area1 = %d, area2 = %d\n",
score, count, area1, area2); */
return score;
}