Browse Source

Fixed the hashing algorithm to use Longs and also added an AHash class

master
Drew Short 11 years ago
parent
commit
3ce5f16313
  1. 42
      src/main/scala/com/sothr/imagetools/hash/AHash.scala
  2. 12
      src/main/scala/com/sothr/imagetools/hash/DHash.scala
  3. 27
      src/test/scala/com/sothr/imagetools/hash/HashServiceTest.scala

42
src/main/scala/com/sothr/imagetools/hash/AHash.scala

@ -1,10 +1,48 @@
package com.sothr.imagetools.hash package com.sothr.imagetools.hash
import grizzled.slf4j.Logging
/** /**
* Created by dev on 1/22/14. * Created by dev on 1/22/14.
*/ */
object AHash extends PerceptualHasher {
object AHash extends PerceptualHasher with Logging {
def getHash(imageData: Array[Array[Int]]): Long = { def getHash(imageData: Array[Array[Int]]): Long = {
return 0L
debug("Generating AHash")
val width = imageData.length
val height = imageData(0).length
debug(s"Image data size: ${width}x${height}")
//calculate average pixel
var total = 0
for (row <- 0 until height) {
for (col <- 0 until width) {
total += imageData(row)(col)
}
}
val mean = total / (height * width)
//calculate ahash
var hash = 0L
for (row <- 0 until height by 2) {
//process each column
for (col <- 0 until width by 1) {
hash <<= 1
val pixel = imageData(row)(col)
//If the current pixel is at or above the mean, store it as a one, else store it as a zero
if (pixel >= mean) hash |= 1 else hash |= 0
}
if ((row +1) < width) {
val nextRow = row + 1
//process each column
for (col <- (width - 1) to 0 by -1) {
hash <<= 1
val pixel = imageData(nextRow)(col)
if (pixel >= mean) hash |= 1 else hash |= 0
}
}
}
debug(s"Computed AHash: $hash from ${width * height} pixels")
hash
} }
} }

12
src/main/scala/com/sothr/imagetools/hash/DHash.scala

@ -13,7 +13,7 @@ object DHash extends PerceptualHasher with Logging {
debug(s"Image data size: ${width}x${height}") debug(s"Image data size: ${width}x${height}")
//calculate dhash //calculate dhash
var hash = 0
var hash = 0L
var previousPixel = imageData(height-1)(width-1) var previousPixel = imageData(height-1)(width-1)
var previousLocation = (height-1, width-1) var previousLocation = (height-1, width-1)
if (height % 2 == 0) { if (height % 2 == 0) {
@ -27,10 +27,10 @@ object DHash extends PerceptualHasher with Logging {
hash <<= 1 hash <<= 1
val pixel = imageData(row)(col) val pixel = imageData(row)(col)
//debug(s"previousPixel: $previousPixel currentPixel: $pixel previousLocation: $previousLocation currentLocation: (${row},${col})") //debug(s"previousPixel: $previousPixel currentPixel: $pixel previousLocation: $previousLocation currentLocation: (${row},${col})")
//binary or the current bit based on whether the value
//binary of the current bit based on whether the value
//of the current pixel is greater or equal to the previous pixel //of the current pixel is greater or equal to the previous pixel
if (pixel >= previousPixel) hash |= 1 else hash |= 0 if (pixel >= previousPixel) hash |= 1 else hash |= 0
//debug(s"hash: $hash")
//debug(s"(${row},${col})=$pixel hash=${hash.toBinaryString}")
previousPixel = pixel previousPixel = pixel
previousLocation = (row, col) previousLocation = (row, col)
} }
@ -42,16 +42,14 @@ object DHash extends PerceptualHasher with Logging {
hash <<= 1 hash <<= 1
val pixel = imageData(nextRow)(col) val pixel = imageData(nextRow)(col)
//debug(s"previousPixel: $previousPixel currentPixel: $pixel previousLocation: $previousLocation currentLocation: (${nextRow},${col})") //debug(s"previousPixel: $previousPixel currentPixel: $pixel previousLocation: $previousLocation currentLocation: (${nextRow},${col})")
//binary or the current bit based on whether the value
//of the current pixel is greater or equal to the previous pixel
if (pixel >= previousPixel) hash |= 1 else hash |= 0 if (pixel >= previousPixel) hash |= 1 else hash |= 0
//debug(s"hash: $hash")
//debug(s"(${row},${col})=$pixel hash=${hash.toBinaryString}")
previousPixel = pixel previousPixel = pixel
previousLocation = (nextRow, col) previousLocation = (nextRow, col)
} }
} }
} }
debug(s"Computed Hash: $hash from ${width * height} pixels")
debug(s"Computed DHash: $hash from ${width * height} pixels")
hash hash
} }
} }

27
src/test/scala/com/sothr/imagetools/hash/HashServiceTest.scala

@ -44,6 +44,21 @@ class HashServiceTest extends BaseTest {
assert(true) assert(true)
} }
test("Confirm Largest DHash Output ") {
val testData:Array[Array[Int]] = Array(
Array(1,2,3,4,5,6,7,8),
Array(16,15,14,13,12,11,10,9),
Array(17,18,19,20,21,22,23,24),
Array(32,31,30,29,28,27,26,25),
Array(33,34,35,36,37,38,39,40),
Array(48,47,46,45,44,43,42,41),
Array(49,50,51,52,53,54,55,56),
Array(64,63,62,61,60,59,58,57))
val hash = DHash.getHash(testData)
debug(s"Hash of test array: $hash")
assert(hash == (Long.MaxValue))
}
test("Calculate DHash Large Sample Image 1") { test("Calculate DHash Large Sample Image 1") {
debug("Starting 'Calculate DHash Large Sample Image 1' test") debug("Starting 'Calculate DHash Large Sample Image 1' test")
val sample = new File(TestParams.LargeSampleImage1) val sample = new File(TestParams.LargeSampleImage1)
@ -51,8 +66,8 @@ class HashServiceTest extends BaseTest {
val image = ImageIO.read(sample) val image = ImageIO.read(sample)
debug(s"Image: width: ${image.getWidth} height: ${image.getHeight}") debug(s"Image: width: ${image.getWidth} height: ${image.getHeight}")
val hash = HashService.getDhash(image) val hash = HashService.getDhash(image)
debug(s"Testing that $hash = -1689609389L")
assert(hash == -1689609389L)
debug(s"Testing that $hash = 4004374827879799635L")
assert(hash == 4004374827879799635L)
} }
test("Calculate DHash Medium Sample Image 1") { test("Calculate DHash Medium Sample Image 1") {
@ -62,8 +77,8 @@ class HashServiceTest extends BaseTest {
val image = ImageIO.read(sample) val image = ImageIO.read(sample)
debug(s"Image: width: ${image.getWidth} height: ${image.getHeight}") debug(s"Image: width: ${image.getWidth} height: ${image.getHeight}")
val hash = HashService.getDhash(image) val hash = HashService.getDhash(image)
debug(s"Testing that $hash = -1689609389L")
assert(hash == -1689609389L)
debug(s"Testing that $hash = 4004374827879799635L")
assert(hash == 4004374827879799635L)
} }
test("Calculate DHash Small Sample Image 1") { test("Calculate DHash Small Sample Image 1") {
@ -73,8 +88,8 @@ class HashServiceTest extends BaseTest {
val image = ImageIO.read(sample) val image = ImageIO.read(sample)
debug(s"Image: width: ${image.getWidth} height: ${image.getHeight}") debug(s"Image: width: ${image.getWidth} height: ${image.getHeight}")
val hash = HashService.getDhash(image) val hash = HashService.getDhash(image)
debug(s"Testing that $hash = -1689609389L")
assert(hash == -1689609389L)
debug(s"Testing that $hash = 4004383623972821843L")
assert(hash == 4004383623972821843L)
} }
test("DHash Of Large, Medium, And Small Sample 1 Must Be Similar") { test("DHash Of Large, Medium, And Small Sample 1 Must Be Similar") {

Loading…
Cancel
Save