• C

Comparing two JPG Files

I am planning to write a program for my security survillence system. Basically a JPG file will be capture every once and a while. A program will then compare two jpg files, and should there be any differences, I will upload it to the web server.

I would need the help to get the comparing mechanism start and going, would appreciate any help from it.

BTW, This program will be running on Linux.

TIA
-=Terence=-
kachanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

TriskelionCommented:
You pose a difficult question.
Will the lighting ever change in the room where the camera is pointing?  Does that matter?

Will the JPG images be the same size every time?

If the lighting changes and the images are different sizes, you will need a pretty complicated algorithm to judge the differences.  If everything usually remains the same, you can start with a simple byte by byte comparison of file 1 and file 2.
0
kachanAuthor Commented:
Can you show me how to compare it byte by byte??

Thanks
0
cadabraCommented:
I'm not into image enhancing algorithms, but maybe you can find some sort of library for dealing with imaging (normalization, comparison, pattern/edge detection etc.), or write one of your own.

If the camera is fixed (not rotating)
and the frame is constant (no zooming)
and the lighting is fixed (no fluctations), Then a comparison or XORing pixels, to identify areas that
have changed, could be considered.
However, I suspect the pictures should
first pass some sort of filtering
before comparison to remove white
noise from the system.

Also there is a problem of how often
your jpg is captured, and whether things
may happen between image captures,
which may be undetected.

Maybe  it would be simpler and more reliable to install a motion detector, which will initiate upload to your site ?

Of course this solution is less challenging intellecutally, and I personally hope you continue to pursue the first solution :)
0
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

AlexVirochovskyCommented:
Next is programm compare every files:
int CompareFiles(char *szF1, char *szF2)
{
  int nRet = 0;
  FILE *f1 = fopen (szF1, "rb");
  FILE *f2 = fopen (szF2, "rb");
  if (f1 && f2)
    {
      char szMem1[1024], szMem2[1024];
      while (!feof(f1) && !feof(f2))
       {
          int len1 = fread(szMem1,1,1024,f1);
          int len1 = fread(szMem1,1,1024,f2);
          if (len1 != len2)
            {
              bRet = -1; break;
            }
          if (memcmp(szMem1, szMem2,1024))
            {
              bRet = -1; break;
            }
       }
    }
   else
     nRet = -1;
   if (f1)
     fclose(f1);
   if (f2)
     fclose(f1);
   return nRet;
}
nRet = 0: same, -1: other
Alex
0
TriskelionCommented:
Well... I'll post it anyway...
Keep in mind, you can also use some type of OS file compare utility.


#include <stdio.h>
#include <memory.h>
/*
      Return Values:
      0=Files are exactly the same
      1=Command-line parameters not valid
      2=Input file 1 cannot be opened
      3=Input file 2 cannot be opened
      4=Bytes in files are different.
*/
int main(int argc, char ** argv)
{
      auto            FILE      *      hanInputFile1      =      NULL;
      auto            FILE      *      hanInputFile2      =      NULL;
      /**/
      static      unsigned char            uchOneKData1[1024];
      static      unsigned char            uchOneKData2[1024];
      /**/
      auto            int            intReturn=0;
      auto            int            intAmountRead1=0;
      auto            int            intAmountRead2=0;

      /**/
      if (argc<3)
            {
            puts("bbyb {file1} {file2}");
            return      1;      /* connand-line arguments not valid */
            }

      /*/////////////////////
      //      open the input file
      */
      if (NULL==(hanInputFile1=fopen(argv[1], "rb")))
            {
            puts("Cannot find first input file");
            return      2;      /*      input file not open or not found */
            }

      /*/////////////////////
      //      open the output file
      */
      if (NULL==(hanInputFile2=fopen(argv[2], "rb")))
            {
            fclose(hanInputFile1);
            puts("Cannot find second input file");
            return      3;      /*      input file not open or not found */
            }

      /* depending on your OS, you should add some file size checking here */

      /*/////////////////////////////////////////////////////
      //      scan through the input file and make the output file
      */
      while (!feof(hanInputFile1) && !feof(hanInputFile2))
            {
            /* swap the size and count parameters in fread to handle EOF better */
            intAmountRead1=fread(uchOneKData1, 1, sizeof(uchOneKData1), hanInputFile1);
            intAmountRead2=fread(uchOneKData2, 1, sizeof(uchOneKData2), hanInputFile2);

            if (0 !=memcmp(uchOneKData1, uchOneKData2, intAmountRead1))
                  {
                  intReturn=4;
                  puts("files have different bytes");
                  break;
                  }
            }

      /*///////////////////////////////
      //      close the files and exit to OS
      */
      fclose(hanInputFile1);
      fclose(hanInputFile2);
      if (0==intReturn)
            {
            puts("same/same");
            }
      return      intReturn;
}
0
jhanceCommented:
I hate to throw water on your fire here but comparing JPEG files byte for byte is not going to work.  JPEG is non-deterministic.  That means that even given the SAME input image, the output JPEG file is not guaranteed to be the same.  So right off, you will always find a difference.  Second, even the most minute detail changed from the camera would modify the image and cause a difference even if JPEG were deterministic.  So you've got two strikes against you.

Comparing images is a serious pattern recognition problem and there is no simple solution.  Very complex and expensive equipment is needed even to detect the simplest differences in a camera image.  Some manfacturing equipment uses "machine vision" and can detect the presence or absence of a component on a circuit board.
0
ozoCommented:
expand the JPEG images to bitmap images, then compare their Fourier transforms
0
jhanceCommented:
ozo,

Interesting idea but still not a valid comparison.  There are many (in fact ther are an infinte number) of marketly different images that would produce the same Fourier series.  Given a limited set of input images that you might get from a fixed survellience camera, a grade of how similar the images are might be made from a comparison of the Fourier coefficients.
0
nils pipenbrinckCommented:
ehm....

folks.. comparing binary files doesn't work..

and doing fft stuff is an overkill.. as usual the easiest way is one of the best.

you can do the following:

decompress the jpeg images using the jpeg library (no problem with linux.. good chances, that the lib is already installed on your system).

then just count the number of pixel that differ from the previus image.

some pseudo code could look like this:

int different_pixels = 0;

for (int i=0; i<pixelcount; i++)
{
  r = pixel[i].r - pixel2[i].r;
  g = pixel[i].g - pixel2[i].g;
  b = pixel[i].b - pixel2[i].b;
  value = sqrt (r*r+g*g+b*b);
  if (value > 40)
    different_pixels++;
}

you can say, that if more than 10% of your analysed pixels differ from the last image, then you have a significant
change in the images.

just an idea..



0
jhanceCommented:
nils,

I think there are flaws in your idea.  

Remember, this is an image from a video camera.  The camera doesn't always capture the image in just the same way.  If the scan is off by just one line up or down, you may have most of the pixels in the new image off from the old one even though the scene is exactly the same.  So you need to do some type of 2-dimensional averaging, comparing an area in the old image with a matrix of pixels in the new one and trying to draw some meaningful comparison.  But it's a compromise.  The smaller the area the greater the sensitivity but the greater the probability of an artifact of the video capture causing a false difference.  The larger the area the less sensitive to artifacts but the less sensitive it is to real changes as well.

What about pixel intensity?  These things are 0/1, they are either color or grey scale.  What about a pixel that is RGB(128, 128, 128) in one image and RGB(129, 128, 128) in the 2nd one?  Are they the same?  What is the threshold you will tolerate?

I'll go back to my earlier assertion, there is NO simple-minded quick-and-dirty code snippet that will solve this.  It's a tough problem and pattern recognition and image processing is a field with a lot of research going on.  Solving problems like this would be a PhD research project not a 100 pt. EE question.
0
graham_kCommented:
so long as you know that you are re-inventing the wheel.  I saw exactly this a month or two ago. I think that if you start from http://www.x10.com and dig about a bit you will find it.
0
cadabraCommented:
I saw a link in the perl discussion area which may be worth a look:

http://www.wizards.dupont.com/cristy/ImageMagick.html
0
SlartiCommented:
I agree with jhance. Anybody who had a good solution to this problem wouldn't be writing about it here. They would be busy forming a startup.
0
DannemandCommented:
I think my approach would be to decode the image, and then remove the higher frequencies of the image as that's where grit, noise and flies would appear and assume that something relevant like a person would show in a low frequency and do bit to bit comparison of the lower frequencies (perhaps leaving out the DC-component).
0
AlexVirochovskyCommented:
kachan, what do you think about expert's
prepositions?
0
AlexVirochovskyCommented:
kachan, i thing , i reply to part of you Q:
>>Can you show me how to compare it byte by byte??
About all you Q, i think, that jhance
took ecxellent analis and no to add.
Sorry, but  seems me, that you lost interest to you Q and pity to expert's
efforts to help you.
jhance, if i get PTS to this Q, i 'll send you same summe.
Alex
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.