我试图实现迭代图像字节数组的图像算法。
(我试图在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示例中一样,但我觉得我更喜欢这种方法。 :)
答案 0 :(得分:4)
我认为您可以使用此
删除alpha示例代码:
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)
}
这里假设data1
和data2
是带有的数组
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
确保两个数组都具有相同的元素数。