How can I compare two NSImages for differences?

2020-06-22 01:20发布

I'm attempting to gauge the percentage difference between two images.

Having done a lot of reading I seem to have a number of options but I'm not sure what the best method to follow for:

  1. Ease of coding
  2. Performance.

The methods I've seen are:

Non language specific - academic Image comparison - fast algorithm and Mac specific direct pixel access http://www.markj.net/iphone-uiimage-pixel-color/

Does anyone have any advice about what solutions make most sense for the above two cases and have code samples to show how to apply them?

5条回答
够拽才男人
2楼-- · 2020-06-22 01:33

It is really difficult to suggest something when you don't tell us more about the images or the variations. Are they shapes? Are they the different objects and you want to know what class of objects? Are they the same object and you want to distinguish the object instance? Are they faces? Are they fingerprints? Are the objects in the same pose? Under the same illumination?

When you say performance, what exactly do you mean? How large are the images? All in all it really depends. With what you've said if it is only ease of coding and performance I would suggest to just find the absolute value of the difference of pixels. That is super easy to code and about as fast as it gets, but really unlikely to work for anything other than the most synthetic examples.

That being said I would like to point you to: DHOG, GLOH, SURF and SIFT.

查看更多
男人必须洒脱
3楼-- · 2020-06-22 01:41

Out of the methods described in your first link, the histogram comparison method is by far the simplest to code and the fastest. However key point matching will provide far more accurate results since you want to know a precise number describing the difference between two images.

To implement the histogram method, I would do the following:

  1. Compute the red, green, and blue histograms of each image
  2. Add up the differences between each bucket
  3. If the difference is above a certain threshold, then the percentage is 0%
  4. Otherwise the colors found in the images are similar. So then do a pixel by pixel comparison and convert the difference into a percentage.

I don't know any precise algorithms for finding the key points of an image. However once you find them for each image you can do a pixel by pixel comparison for each of the key points.

查看更多
疯言疯语
4楼-- · 2020-06-22 01:42

This is some old nasty FORTRAN, but should give you the basic approach. It is not that difficult at all. Due to the fact that I am doing it on a two colour pallette you would do this operation for R, G and B. That is compute the intensities or values in each cell/pixal, store them in some array. Do the same for the other image, and subtract one array from the other, this will leave you with some coulorfull subtraction image. My advice would be to do as the lads suggest above, compute the magnitude of the sum of the R, G and B componants so you just get one value. Write that to array, do the same for the other image, then subtract. Then create a new range for either R, G or B and map the resulting subtracted array to this, the will enable a much clearer picture as a result.

* =============================================================
      SUBROUTINE SUBTRACT(FNAME1,FNAME2,IOS)
*     This routine writes a model to files
* =============================================================
*    Common :
      INCLUDE 'CONST.CMN'
      INCLUDE 'IO.CMN'
      INCLUDE 'SYNCH.CMN'
      INCLUDE 'PGP.CMN'
*    Input :
      CHARACTER fname1*(sznam),fname2*(sznam)
*    Output :
      integer IOS
*    Variables:
       logical glue
       character fullname*(szlin)
       character dir*(szlin),ftype*(3)
       integer i,j,nxy1,nxy2
       real si1(2*maxc,2*maxc),si2(2*maxc,2*maxc)
* =================================================================

       IOS = 1
       nomap=.true.

       ftype='map'
       dir='./pictures'

!    reading first image
       if(.not.glue(dir,fname2,ftype,fullname))then
           write(*,31) fullname
           return
       endif

       OPEN(unit2,status='old',name=fullname,form='unformatted',err=10,iostat=ios)

       read(unit2,err=11)nxy2
       read(unit2,err=11)rad,dxy
       do i=1,nxy2
          do j=1,nxy2
             read(unit2,err=11)si2(i,j)
          enddo
       enddo

       CLOSE(unit2)


!    reading second image
       if(.not.glue(dir,fname1,ftype,fullname))then
           write(*,31) fullname
           return
       endif

       OPEN(unit2,status='old',name=fullname,form='unformatted',err=10,iostat=ios)

       read(unit2,err=11)nxy1
       read(unit2,err=11)rad,dxy
       do i=1,nxy1
          do j=1,nxy1
             read(unit2,err=11)si1(i,j)
          enddo
       enddo

       CLOSE(unit2)

!    substracting images 
       if(nxy1.eq.nxy2)then 
           nxy=nxy1
           do i=1,nxy1
              do j=1,nxy1
                 si(i,j)=si2(i,j)-si1(i,j)
              enddo
           enddo
       else
          print *,'SUBSTRACT: Different sizes of image arrays'
          IOS=0 
          return
       endif

*  normal finishing
       IOS=0 
       nomap=.false.
       return

*  exceptional finishing
10     write (*,30) fullname
       return
11     write (*,32) fullname
       return

30     format('Cannot open file   ',72A)
31     format('Improper filename   ',72A)
32     format('Error reading from file   ',72A)

      end
! =============================================================

Hope this is of some use. All the best.

查看更多
狗以群分
5楼-- · 2020-06-22 01:54

I've had success calculating the difference between two images using the histogram technique mentioned here. redmoskito's answer in the SO question you linked to was actually my inspiration!

The following is an overview of the algorithm I used:

  1. Convert the images to grayscale—compare one channel instead of three.
  2. Divide each image into an n * n grid of "subimages". Then, for subimage pair:
    1. Calculate their colour composition histograms.
    2. Calculate the absolute difference between the two histograms.
  3. The maximum difference found between two subimages is a measure of the two images' difference. Other metrics could also be used (e.g. the average difference betwen subimages).

As tskuzzy noted in his answer, if your ultimate goal is a binary "yes, these two images are (roughly) the same" or "no, they're not", you need some meaningful threshold value. You could produce such a value by passing images into the algorithm and tweaking the threshold based on its output and how similar you think the images are. A form of machine learning, I suppose.

I recently wrote a blog post on this very topic, albeit as part of a larger goal. I also created a simple iPhone app to demonstrate the algorithm. You can find the source on GitHub; perhaps it will help?

查看更多
霸刀☆藐视天下
6楼-- · 2020-06-22 01:55

You can use fairly basic subtraction technique that the lads above suggested. @carlosdc has hit the nail on the head with regard to the type of image this basic technique can be used for. I have attached an example so you can see the results for yourself.

The first shows a image from a simulation at some time t. A second image was subtracted away from the first which was taken some (simulation) time later t + dt. The subtracted image (in black and white for clarity) then shows how the simulation has changed in that time. This was done as described above and is very powerful and easy to code.

Hope this aids you in some way

Image of simulated syncrotron emission from the Crab Nebula

Subtraction of one image from another taken 109 days of simulated time later

查看更多
登录 后发表回答