Swift:从数组中过滤每第4个项目

时间:2016-12-19 16:56:12

标签: ios swift algorithm

我试图实现迭代图像字节数组的图像算法。

(我试图在Swift中复制这个... https://rosettacode.org/wiki/Percentage_difference_between_images#JavaScript

但是,我需要忽略字母字节。

我试图对它很聪明但是我已经不能再从字节数组中删除第4项了。

有没有一种简单的方法可以做到这一点?

func compareImages(image1: UIImage, image2: UIImage) -> Double {
    // get data from images
    guard let data1 = UIImageJPEGRepresentation(image1, 1),
        let data2 = UIImageJPEGRepresentation(image2, 1) else {
            return -1
    }

    // zip up byte arrays
    return zip([UInt8](data1), [UInt8](data2))
        // sum the difference of the bytes divided by 255
        .reduce(0.0) { $0 + Double(abs(Int32($1.0) - Int32($1.1))) / 255.0 }
        // divide by the number of rbg bytes
        / Double(image1.size.width * image1.size.height * 3)
}

如果我能够从每个数组中删除/忽略第4个字节,这将完全符合我的要求吗?

另一种选择是一次跨越数组4,就像在链接到的Javascript示例中一样,但我觉得我更喜欢这种方法。 :)

5 个答案:

答案 0 :(得分:4)

我认为您可以使用此

删除alpha
  1. 枚举以获得对(索引,元素)
  2. 过滤以删除alpha
  3. 映射以将对转换为仅元素
  4. 示例代码:

    var array = [0,1,2,3,4,5,6,7,8,9]
    
    array = array.enumerated().filter { index, element in
        return index % 4 != 3
    }.map { index, element in
        return element
    }
    
    print(array) // [0,1,2,4,5,6,8,9]
    

答案 1 :(得分:1)

另一个,只是一点点的方式。

var foo = [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
var bar = [Int]()

for i in stride(from: 0, to: foo.count - 3, by: 4) {
    bar += foo[i..<i+3]
}

bar //[1, 2, 3, 1, 2, 3, 1, 2, 3]

答案 2 :(得分:1)

图像数据可能很大,因此我会避免创建 中间数组只删除每个第4个元素。

您的zip + reduce方法可以与enumerated()结合使用 以便在求和中忽略每个第4个字节:

func rgbdiff(data1: [UInt8], data2: [UInt8], width: Int, height: Int) -> Double {
    return zip(data1, data2).enumerated().reduce(0.0) {
        $1.offset % 4 == 3 ? $0 : $0 + abs(Double($1.element.0) - Double($1.element.1))/255.0
    } / Double(width * height * 3)
}

这里假设data1data2是带有的数组 RGBA像素数据和两个图像具有相同的尺寸。

您还可以处理Data值而无需转换为数组:

func rgbdiff(data1: Data, data2: Data, width: Int, height: Int) -> Double {
      // ... same function ...
}

因为Swift 3 Data是其字节的Iterator

答案 3 :(得分:1)

好的,对于任何想要更新过滤数组但也能获得正确像素数据的人......

我使用了这里的答案版本...... Get pixel data as array from UIImage/CGImage in swift

并且@ MartinR的答案是创建以下两个函数......

func pixelValues(fromCGImage imageRef: CGImage?) -> [UInt8]?
{
    var width = 0
    var height = 0
    var pixelValues: [UInt8]?

    if let imageRef = imageRef {
        width = imageRef.width
        height = imageRef.height
        let bitsPerComponent = imageRef.bitsPerComponent
        let bytesPerRow = imageRef.bytesPerRow
        let totalBytes = height * bytesPerRow
        let bitmapInfo = imageRef.bitmapInfo

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        var intensities = [UInt8](repeating: 0, count: totalBytes)

        let contextRef = CGContext(data: &intensities, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
        contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(width), height: CGFloat(height)))

        pixelValues = intensities
    }

    return pixelValues
}

func compareImages(image1: UIImage, image2: UIImage) -> Double? {
    guard let data1 = pixelValues(fromCGImage: image1.cgImage),
        let data2 = pixelValues(fromCGImage: image2.cgImage),
        data1.count == data2.count else {
            return nil
    }

    let width = Double(image1.size.width)
    let height = Double(image1.size.height)

    return zip(data1, data2)
        .enumerated()
        .reduce(0.0) {
            $1.offset % 4 == 3 ? $0 : $0 + abs(Double($1.element.0) - Double($1.element.1))
        }
        * 100 / (width * height * 3.0) / 255.0
}

一旦我弄清楚如何,我就会将它提交给Rosetta网站。

答案 4 :(得分:0)

let array1 = [1, 2, 3, 255, 5, 6, 7, 255, 8, 9, 10, 255]
let array2 = [1, 2, 3, 0, 5, 6, 7, 0, 8, 9, 10, 0]

let difference = zip(array1, array2)                   // Make one sequence from two arrays
    .enumerated()                                      // Assign each pair an index
    .filter({ $0.offset % 4 != 3 })                    // Strip away each 4th pair
    .map({ $0.element })                               // Discard indices
    .reduce(0, { $0 + Swift.abs($1.0 - $1.1) }) / 255  // Do the math

print(difference) // 0

确保两个数组都具有相同的元素数。