PhotosImageClassfier+Blurry.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. //
  2. // PhotosImageClassfier+Blurry.swift
  3. // Demo
  4. //
  5. // Created by Groot on 2025/4/27.
  6. //
  7. import UIKit
  8. extension PhotosImageClassifier {
  9. static func detectBlurryImages(item: ImageItem) -> Bool {
  10. guard let image = item.thumbnailImage else { return false }
  11. return isImageBlurry(image)
  12. }
  13. private static func isImageBlurry(_ image: UIImage) -> Bool {
  14. guard let cgImage = image.cgImage else { return false }
  15. // 使用更小的采样区域
  16. let width = cgImage.width
  17. let height = cgImage.height
  18. let pixelStride = 4 // 改名为pixelStride,避免与函数名冲突
  19. // 提前检查图像尺寸是否合法
  20. guard width > (2 * pixelStride), height > (2 * pixelStride) else {
  21. return false
  22. }
  23. // 使用vImage进行快速处理
  24. var buffer = [UInt8](repeating: 0, count: width * height)
  25. let colorSpace = CGColorSpaceCreateDeviceGray()
  26. guard let context = CGContext(
  27. data: &buffer,
  28. width: width,
  29. height: height,
  30. bitsPerComponent: 8,
  31. bytesPerRow: width,
  32. space: colorSpace,
  33. bitmapInfo: CGImageAlphaInfo.none.rawValue
  34. ) else {
  35. return false
  36. }
  37. context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
  38. // 使用拉普拉斯算子的简化版本
  39. var score: Double = 0
  40. var sampledPixels = 0
  41. // 只采样图像的一部分区域
  42. let sampleRows = 10
  43. let sampleCols = 10
  44. // 计算步长
  45. let rowStep = max(1, height / sampleRows)
  46. let colStep = max(1, width / sampleCols)
  47. // 使用Swift的stride函数
  48. for y in Swift.stride(from: pixelStride, to: height - pixelStride, by: rowStep) {
  49. for x in Swift.stride(from: pixelStride, to: width - pixelStride, by: colStep) {
  50. let current = Int(buffer[y * width + x])
  51. let left = Int(buffer[y * width + (x - pixelStride)])
  52. let right = Int(buffer[y * width + (x + pixelStride)])
  53. let top = Int(buffer[(y - pixelStride) * width + x])
  54. let bottom = Int(buffer[(y + pixelStride) * width + x])
  55. // 简化的边缘检测
  56. let dx = abs(left - right)
  57. let dy = abs(top - bottom)
  58. score += Double(max(dx, dy))
  59. sampledPixels += 1
  60. }
  61. }
  62. // 避免除以零
  63. guard sampledPixels > 0 else { return false }
  64. // 归一化分数
  65. let normalizedScore = score / Double(sampledPixels)
  66. // 调整阈值
  67. let threshold = 15.0
  68. return normalizedScore < threshold
  69. }
  70. }