Swift - 在CGPoint处比较颜色

13

我有两张图片想要比较,如果像素颜色相同则保存它。 我使用这个 UIImage 扩展函数检测像素颜色:

func getPixelColor(pos: CGPoint) -> ??? {

    let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(self.CGImage))
    let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

    let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4

    let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
    let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
    let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
    let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)

    return ???
}
例如,我在图片1上运行扫描仪并将其保存在一个数组中?还是字典?之后,当我拥有来自2张图片的信息进行比较时,我会运行图片2上的扫描仪,并使用哪个函数?
我想看看从2个图像中哪个CGPoint的像素颜色是相同的?
更新: 我更新了getPixelColor,让它返回“(pos)(r)(g)(b)(a)”,然后我创建了这个函数,只留下了重复项(在使用此函数之前,您必须对数组进行.sort()操作!)
extension Array where Element : Equatable {
    var duplicates: [Element] {
        var arr:[Element] = []
        var start = 0
        var start2 = 1
        for _ in 0...self.count{
            if(start2<self.count){
                if(self[start] == self[start2]){
                    if(arr.contains(self[start])==false){
                        arr.append(self[start])
                    }
                }
                start+=1
                start2+=1
            }
        }
        return arr
    }
}

这让我返回了类似以下的东西:"(609.0, 47.0)1.01.01.01.0"。 我知道此时颜色是黑色,我执行x-536以适应iPhone 5屏幕,当我尝试再次绘制时它画错了...也许我不能正确地做到这一点..请帮忙?


返回一个UIColor,并检查它们是否相等?请注意,颜色的差异是一个讨论得比较多的话题,有很多不同的方法。 - Larme
你也在检查每个像素吗?如果你正在扫描这些图片,我认为你很难做到完美地对齐每个像素,甚至在开始担心每个颜色在每个维度上是否正确扫描到1/255之前。 - Russell
UIColor不符合可哈希协议... 一些像素是100%相同的,我想知道哪些CGPoint是相同的... - Bogdan Bogdanov
2个回答

4

将UIImage扩展返回UIColor。使用此方法来比较两个图像的每个像素。如果两个像素匹配,则将颜色添加到一个数组中。

extension UIImage {
    func getPixelColor(pos: CGPoint) -> UIColor {

        let pixelData = CGDataProviderCopyData(CGImageGetDataProvider(self.CGImage))
        let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

        let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4

        let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
        let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
        let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
        let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)

        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
}


func findMatchingPixels(aImage: UIImage, _ bImage: UIImage) -> [[UIColor?]] {
    guard aImage.size == bImage.size else { fatalError("images must be the same size") }

    var matchingColors: [[UIColor?]] = []
    for y in 0..<Int(aImage.size.height) {
        var currentRow = [UIColor?]()
        for x in 0..<Int(aImage.size.width) {
            let aColor = aImage.getPixelColor(CGPoint(x: x, y: y))
            let colorsMatch = bImage.getPixelColor(CGPoint(x: x, y: y)) == aColor
            currentRow.append(colorsMatch ? aColor : nil)
        }
        matchingColors.append(currentRow)
    }
    return matchingColors
}

使用方法如下:

let matchingPixels = findMatchingPixels(UIImage(named: "imageA.png")!, UIImage(named: "imageB.png")!)
if let colorForOrigin = matchingPixels[0][0] {
   print("the images have the same color, it is: \(colorForOrigin)")
} else {
   print("the images do not have the same color at (0,0)")
}

为了简化,我让findMatchingPixels()需要图像具有相同的大小,但是允许不同大小的图像也不需要花费太多时间。 更新 如果您只想要匹配的像素,则可以返回如下元组:
func findMatchingPixels(aImage: UIImage, _ bImage: UIImage) -> [(CGPoint, UIColor)] {
    guard aImage.size == bImage.size else { fatalError("images must be the same size") }

    var matchingColors = [(CGPoint, UIColor)]()
    for y in 0..<Int(aImage.size.height) {
        for x in 0..<Int(aImage.size.width) {
            let aColor = aImage.getPixelColor(CGPoint(x: x, y: y))
            guard bImage.getPixelColor(CGPoint(x: x, y: y)) == aColor else { continue }

            matchingColors.append((CGPoint(x: x, y: y), aColor))
        }
    }
    return matchingColors
}

0

为什么不尝试一种不同的方法呢?

核心图像滤镜CIDifferenceBlendMode将返回一个全黑的图像,如果传入两个相同的图像和一个具有非黑色区域的图像,其中两个图像不同。将其传递到CIAreaMaximum中,它将返回一个包含最大像素的1x1图像:如果最大值为0,则知道您有两个相同的图像,如果最大值大于零,则两个图像不同。

给定两个CIImage实例,imageAimageB,以下是代码:

let ciContext = CIContext()

let difference = imageA
    .imageByApplyingFilter("CIDifferenceBlendMode",
        withInputParameters: [
            kCIInputBackgroundImageKey: imageB])
    .imageByApplyingFilter("CIAreaMaximum",
        withInputParameters: [
            kCIInputExtentKey: CIVector(CGRect: imageA.extent)])

let totalBytes = 4
let bitmap = calloc(totalBytes, sizeof(UInt8))

ciContext.render(difference,
    toBitmap: bitmap,
    rowBytes: totalBytes,
    bounds: difference.extent,
    format: kCIFormatRGBA8,
    colorSpace: nil)

let rgba = UnsafeBufferPointer<UInt8>(
    start: UnsafePointer<UInt8>(bitmap),
    count: totalBytes)

let red = rgba[0]
let green = rgba[1]
let blue = rgba[2]

如果红色绿色蓝色不为零,则您知道图像是不同的!

一些像素是完全相同的,我想知道它们在哪个CGPoint上是相同的... - Bogdan Bogdanov
啊,好的,我误解了“我有两张图片想要比较,如果像素颜色相同就保存它”的意思。我以为你只想在两张图片完全相同的情况下保存一张图片。 - Flex Monkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接