Warning: session_start(): open(/var/lib/php/sessions/sess_7ug43aep9drkq122sjkicgsq5p, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
// probabilistic (of course)
srecord noeq ImageSimilarityAtScale (
IIntegralImage img1,
IIntegralImage img2,
int featureSize // smallest block size to be looked at (w/h in pixels)
) extends Probabilistic implements IF0 {
int channels;
LookAtClip root;
int blocksCalculated;
bool verbose;
record LookAtClip(LookAtClip parent, Rect r) implements Runnable {
L children;
// diffs are in range [0;255*channels*pixelsCovered]
double initialDiff, diffsFromChildren, areaCoveredByChildren;
double latestDiff;
double latestDiff() { ret latestDiff; }
double calculateLatestDiff() {
ret latestDiff = initialDiff*(area()-areaCoveredByChildren)+diffsFromChildren;
}
run {
// make initial guess
double sum = 0;
for channel to channels:
sum += sqr(
img1.rectSum(r, channel)-img2.rectSum(r, channel));
initialDiff = sqrt(sum);
if (verbose) printVars(+r, +initialDiff);
++blocksCalculated;
updateMeAndParent();
if (r.w > r.h) {
if (r.w > featureSize)
splitHorizontally();
} else {
if (r.h > featureSize)
splitVertically();
}
}
void splitHorizontally {
split(asList(splitRectInHorizontalHalves(r)));
}
void splitVertically {
split(asList(splitRectInVerticalHalves(r)));
}
void split(L parts) {
double p = 0.99;
children = map(parts, r -> new LookAtClip(this, r));
scheduleAll(p, children);
}
void updateMeAndParent() {
calculateLatestDiff();
if (parent != null) {
parent.diffsFromChildren += latestDiff;
parent.areaCoveredByChildren += area();
parent.updateMeAndParent();
}
}
double area() { ret rectArea(r); }
}
run {
assertEquals("Sizes of compared images have to be equal", img1.getSize(), img2.getSize());
assertEquals("Channel counts of compared images have to be equal", channels = img1.nChannels(), img2.nChannels());
root = new LookAtClip(null, imageRect(img1));
root.run();
}
// similarity between 0 and 1
// it's a best guess until the calculation is complete
public Double similarity aka get() {
ret 1-diff();
}
// difference (1-similarity) between 0 and 1
// (this can be more precise in floating point then similarity)
public double diff() {
ret root.latestDiff()/(root.area()*channels*255);
}
int blocksCalculated() { ret blocksCalculated; }
}