| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- //
- // PhotosImageClassfier+Blurry.swift
- // Demo
- //
- // Created by Groot on 2025/4/27.
- //
- import UIKit
- extension PhotosImageClassifier {
- static func detectBlurryImages(item: ImageItem) -> Bool {
- guard let image = item.thumbnailImage else { return false }
-
- return isImageBlurry(image)
- }
-
- private static func isImageBlurry(_ image: UIImage) -> Bool {
- guard let cgImage = image.cgImage else { return false }
-
- // 使用更小的采样区域
- let width = cgImage.width
- let height = cgImage.height
- let pixelStride = 4 // 改名为pixelStride,避免与函数名冲突
-
- // 提前检查图像尺寸是否合法
- guard width > (2 * pixelStride), height > (2 * pixelStride) else {
- return false
- }
-
- // 使用vImage进行快速处理
- var buffer = [UInt8](repeating: 0, count: width * height)
-
- let colorSpace = CGColorSpaceCreateDeviceGray()
- guard let context = CGContext(
- data: &buffer,
- width: width,
- height: height,
- bitsPerComponent: 8,
- bytesPerRow: width,
- space: colorSpace,
- bitmapInfo: CGImageAlphaInfo.none.rawValue
- ) else {
- return false
- }
-
- context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
-
- // 使用拉普拉斯算子的简化版本
- var score: Double = 0
- var sampledPixels = 0
-
- // 只采样图像的一部分区域
- let sampleRows = 10
- let sampleCols = 10
-
- // 计算步长
- let rowStep = max(1, height / sampleRows)
- let colStep = max(1, width / sampleCols)
-
- // 使用Swift的stride函数
- for y in Swift.stride(from: pixelStride, to: height - pixelStride, by: rowStep) {
- for x in Swift.stride(from: pixelStride, to: width - pixelStride, by: colStep) {
- let current = Int(buffer[y * width + x])
- let left = Int(buffer[y * width + (x - pixelStride)])
- let right = Int(buffer[y * width + (x + pixelStride)])
- let top = Int(buffer[(y - pixelStride) * width + x])
- let bottom = Int(buffer[(y + pixelStride) * width + x])
-
- // 简化的边缘检测
- let dx = abs(left - right)
- let dy = abs(top - bottom)
- score += Double(max(dx, dy))
- sampledPixels += 1
- }
- }
-
- // 避免除以零
- guard sampledPixels > 0 else { return false }
-
- // 归一化分数
- let normalizedScore = score / Double(sampledPixels)
-
- // 调整阈值
- let threshold = 15.0
- return normalizedScore < threshold
- }
- }
|