You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
2.2 KiB

  1. package com.sothr.imagetools.hash
  2. import edu.emory.mathcs.jtransforms.dct.FloatDCT_2D
  3. import grizzled.slf4j.Logging
  4. /**
  5. * Created by dev on 1/22/14.
  6. */
  7. object PHash extends PerceptualHasher with Logging {
  8. def getHash(imageData: Array[Array[Int]]): Long = {
  9. //convert the imageData into a FloatArray
  10. val width = imageData.length
  11. val height = imageData(0).length
  12. //debug(s"Starting with image of ${height}x${width} for PHash")
  13. val imageDataFloat:Array[Array[Float]] = Array.ofDim[Float](height, width)
  14. for (row <- 0 until height) {
  15. for (col <- 0 until width) {
  16. imageDataFloat(row)(col) = imageData(row)(col).toFloat
  17. }
  18. }
  19. //debug("Copied image data to float array for transform")
  20. //debug(s"\n${imageDataFloat.deep.mkString("\n")}")
  21. //perform transform on the data
  22. val dct:FloatDCT_2D = new FloatDCT_2D(height,width)
  23. dct.forward(imageDataFloat, true)
  24. //debug("Converted image data into DCT")
  25. //debug(s"\n${imageDataFloat.deep.mkString("\n")}")
  26. //extract the DCT data
  27. val dctDataWidth:Int = width / 4
  28. val dctDataHeight:Int = height / 4
  29. //calculate the mean
  30. var total = 0.0f
  31. for (row <- 0 until dctDataHeight) {
  32. for (col <- 0 until dctDataWidth) {
  33. total += imageDataFloat(row)(col)
  34. }
  35. }
  36. val mean = total / (dctDataHeight * dctDataWidth)
  37. //debug(s"Calculated mean as $mean from ${total}/${dctDataHeight * dctDataWidth}")
  38. //calculate the hash
  39. var hash = 0L
  40. for (row <- 0 until dctDataHeight by 2) {
  41. //process each column
  42. for (col <- 0 until dctDataWidth by 1) {
  43. hash <<= 1
  44. val pixel = imageDataFloat(row)(col)
  45. //If the current pixel is at or above the mean, store it as a one, else store it as a zero
  46. if (pixel >= mean) hash |= 1 else hash |= 0
  47. }
  48. if ((row +1) < dctDataWidth) {
  49. val nextRow = row + 1
  50. //process each column
  51. for (col <- (dctDataWidth - 1) to 0 by -1) {
  52. hash <<= 1
  53. val pixel = imageDataFloat(nextRow)(col)
  54. if (pixel >= mean) hash |= 1 else hash |= 0
  55. }
  56. }
  57. }
  58. //debug(s"Computed PHash: $hash from ${dctDataWidth * dctDataHeight} pixels")
  59. hash
  60. }
  61. }