Percentage difference between images

Hello,

How can I calculate the percentage difference between images?

I’ve seen it being done in several languages here, except XOJO…
https://rosettacode.org/wiki/Percentage_difference_between_images

OK this is what I plan to do…

I have an endoscope which is displaying the output on a monitor.
If I click on the freeze button of the endoscope the image on the display is now frozen.

I am hoping that if I take two images 100ms apart and compare them I would know if the image is frozen.

Is there another way to do it?

Thanks.

Lennox

If the image is frozen, shouldn’t there be zero difference between them? Ie., if there is any difference at all, then it’s not frozen. Or am I missing something?

It is easy to see if two pictures are identical by using PictureToString and comparing the strings.

That said, the PureBasic code at RosettaCode seems fairly easy to adapt to Xojo.

Hi Tim,

I am of that opinion too but I do not know how these images are created on the display,

OK, what I am planning to do is this, my program will not be able to detect when the user clicks on the endoscope to freeze the picture. So my program will have to know that the user clicked by an indirect method.

So my program will poll the stream, it will take pictures every 100ms, and it will keep two images in memory.
If the two images in memory are not the same then it will purge the first image and create a second image and compare the two, it will continue that process until the two images are the same.

When the two images are the same it will save one of them to disk and continue until the endoscopy procedure is done, it would have saved as many images as the endoscope was clicked.

Does that seem to be a good way? I have no other way of knowing that the endoscope was clicked.

Thanks again.

Lennox

Hi Michel,

I am of that opinion too but the images are not copies of the other. The images are taken from a live stream 100ms apart, I do not know if the two images taken 100ms apart from a live stream, when frozen, will be the same, so comparing them with binary streams may not work.

Thanks.

Lennox

About click : you can detect mouse clicks wherever they happen with system.MouseDown. Use a timer to monitor it, such as :

static deja as boolean = system.mousedown if deja <> system.mousedown then system.DebugLog str(system.mousedown) deja = system.mousedown end if

It won’t tell you that a button has been clicked, but it will let you know where the mouse was, so that may help detect it was in the endoscope software window. Also, that alleviates the need to check every 100ms for the picture. Maybe you simply wait for a click and then analyse the picture.

Thanks Michel,

That’s not how the endoscope works. The endoscope does not have a mouse. There is a button that is pressed that causes the picture on the screen to be frozen, (I deliberately did not say clicked now because I do not want to imply that there is a mouse). The video processor receives that button press and outputs a frozen image on the screen.

The video processor does not store images, it does not have anything to store images. The video processor has a video-output connection which gives a stream, so there is no way to indicate that the button was pressed. So what comes into the computer via a USB connection is a stream.

My program has to process that stream to know that a frozen image is being displayed. So if I capture images 100ms apart and compare them then my program will know if a still image is being displayed and then my program will capture that image.

That is my understanding, I could be wrong. Just seeking opinions as to whether my proposed line of action would work.

Thanks again.

Lennox

Since both images are coming from the same processor, they should have the same encoding/compression applied to them, so they should be identical. In fact, I would expect the processor to have the “frozen” image cached and just be sending the exact same data over and over as the stream.

It’s not that difficult, but you’ll need some basic understanding of image editing from a developers point of view.

I would recommend using something like Einhugur’s picture effects. Bjorn’s plugin contains many image processing functions and is x-plat. http://einhugur.com/Html/Libs.html

From here, you take you two pictures and blend them together with the difference blend mode. This will create a image representing the difference in values from one frame to another.

The next and probably the most difficult stage is then decided on what is an actionable change or not. For instance if the 2 frames are the exact same pixels, you’ll receive a solid black image. However due to compression, this will probably never happen, instead you’ll receive an image with some slight grey values.

From here, I’ll leave you to decide on how best to measure the difference and what is acceptable and what isn’t.

You really need to get samples of 2 frozen images to compare, otherwise it’s just guessing what happens. And if they aren’t identical maybe post them here for us to investigate.

Thanks for all the replies,

I am of Will’s opinion - try it out with two frozen images and see what happens.

I am using Frederik’s project… http://109.235.76.86/webcam_app.xojo_binary_project

Currently I am doing it out on the built in webcam, the webcam works fine, and I am trying external video device but I am not able to get the external video device connected although it shows up in the menu. So, I don’t think the endoscope will work. The endoscope is also an external video device.

I really need some help, I have code in C++ but I do not know how to convert it to Xojo.

If anyone wants to see how I modified Frederick’s code I can send it. It is a Windows only project.

Thanks.

Lennox

A quick and dirty way of getting the ‘percentage’ shift from the difference bland, would be to draw the difference result into a single pixel image and then measure it’s .value from the sole pixel. Note that accuracy will decrease as you reduce the size of the image.

We used a similar technique in the past (with a 4 pixel image) to gauge the overall exposure of a picture, the reduction will create an average of the pixel values (which is why it’s not very accurate), much faster than evaluating each pixel of the difference output.

PictureMBS.CompareImages in MBS Plugin would tell you the number of different pixels.
if that helps.

and I found this FAQ entry:
http://www.monkeybreadsoftware.net/faq-howtocomparetwopictures.shtml

Thanks Christian,

I don’t know if I am using that function correctly. I am using it like this…
Dim pic1, pic2, pic3 As Picture
Dim ThePicture as FolderItem

ThePicture = SpecialFolder.Desktop.Child(“temp 3.png”)
Pic1 = Picture.Open(ThePicture)

ThePicture = SpecialFolder.Desktop.Child(“temp 3copy.png”)
Pic2 = Picture.Open(ThePicture)

// temp 3copy.png is a copy of temp 3.png

ThePicture = SpecialFolder.Desktop.Child(“temp 4.png”)
Pic3 = Picture.Open(ThePicture)

If ComparePictures(Pic1, Pic2) = -1 then
msgbox “Successful! temp 3.png and temp 3copy.png are the same”
else
msgbox “Error! temp 3.png and temp 3copy.png are not the same”
end if

If ComparePictures(Pic1, Pic3) = -1 then
msgbox “Successful! temp 3.png and temp 4.png are the same”
else
msgbox “Error! temp 3.png and temp 4.png are not the same”
end if

I get the error message with both comparisons.

Could you help me with this C++ to XOJO conversion?
This is what is in the close event of the project but it does not seem to terminate the connection with the USBwebcam.

Declare Function SendMessage lib “user32” alias “SendMessageA”(hwnd as integer,wMsg as integer,wParam as integer,lParam as integer)AS integer

DIM START AS INTEGER
DIM G AS INTEGER

START =&H400
G=START+11

CALL SendMessage(CANVAS1.Handle,G,0,0)

This is Microsoft’s recommendation
https://msdn.microsoft.com/en-us/library/windows/desktop/dd756886(v=vs.85).aspx

'capDriverDisconnect macro
'The capDriverDisconnect macro disconnects a capture driver from a capture window. You can use this macro or explicitly send the WM_CAP_DRIVER_DISCONNECT message.
'Syntax

'C++

'BOOL capDriverDisconnect(
'hwnd
');

'Parameters

'hwnd
'Handle to a capture window.
'Return value

'Returns TRUE if successful or FALSE if the capture window is not connected to a capture driver.
'Requirements

'Minimum supported client
'Windows 2000 Professional [desktop apps only]
'Minimum supported server
'Windows 2000 Server [desktop apps only]
'Header
'Vfw.h

https://msdn.microsoft.com/en-us/library/windows/desktop/dd797803(v=vs.85).aspx

Thanks.

Lennox

p.s. Hi Christian, I just saw the notes regarding the function…
“Notes: Remember that this only works on bitmap pictures, so the picture.BitmapMBS function may be useful.”

Could this be the new mutable vs. immutable picture thing? You might need to convert the image before you call the MBS routines.

Which will itself change the image.

What you get when you open a picture in Xojo is not what you started with.
Probably to do with color profiles, but in my experience the colors always change.

[quote=266096:@Jeff Tullin]Which will itself change the image.

What you get when you open a picture in Xojo is not what you started with.
Probably to do with color profiles, but in my experience the colors always change.[/quote]

which should be a moot point, if you are converting two images from the same source, using the same algorithm
plus (my opinion), converting both to 256 gray scale first might give a better analysis, since this will remove 90% of color variations due to factors such as air movement, temp variations etc. (which I guess won’t apply if coming from a digital instrument :slight_smile: )

I’d start experimenting, by taking two images, convert to gray scale, compare pixel by pixel (using RGBSurface), determine an acceptable gray value difference (is 0x010101 close enough to 0x030303?) etc.

Or compare the raw data and not the image representation of that data.

OK, I compared the images after converting them to binary strings, when the strings compare they are the same, I got that over.

Dim pic As Picture
Dim bs as BinaryStream
Dim f2 as FolderItem

f2 = app.gTheEndoscopyImagesFolder.Child(“myPic 3.png”)
Pic = Picture.Open(f2)
if Pic <> nil then
'// Get the image as string
bs = f2.OpenAsBinaryFile
S0 = bs.Read(bs.Length)
S0 = EncodeBase64(S0, 0)

else
msgbox “myPic 3 is nil”
end if

If Keyboard.AsyncControlKey or IsContextualClick then
f2 = app.gTheEndoscopyImagesFolder.Child(“myPic 3copy.png”)
Pic = Picture.Open(f2)
if Pic <> nil then
'// Get the image as string
bs = f2.OpenAsBinaryFile
S1 = bs.Read(bs.Length)
S1 = EncodeBase64(S1, 0)
else
msgbox “myPic 3copy is nil”
end if

else
f2 = app.gTheEndoscopyImagesFolder.Child(“myPic 4.png”)
Pic = Picture.Open(f2)
if Pic <> nil then
'// Get the image as string
bs = f2.OpenAsBinaryFile
S1 = bs.Read(bs.Length)
S1 = EncodeBase64(S1, 0)
else
msgbox “myPic 4 is nil”
end if

end if

If S0 = S1 Then
'msgbox “Frozen”

Pic = Pic.ProportionalScale( LivePicsImageWellDisplays(0).Width, LivePicsImageWellDisplays(0).Height )
LivePicsImageWellDisplays(0).Image = Pic

else
'msgbox “Streaming”

LivePicsImageWellDisplays(0).Image = SadFace

end if

That works.

I did it with images that I have, I have not tried the video processor’s frozen images as yet, but I am of the opinion that I may not be able to do so since the app is not connecting up any external video device connected via usb, although the option to select that device is available.

USB 2861 Device
Your PC ran into a problem and needs to restart. We’re just collecting some error info, and then we’ll restart for you.
If you’d like to know more, you can search online later for this error: SYSTEM SERVICE EXCEPTION (emBDA64.sys)

How can I add an image here?

Thanks.

Lennox