1

I want to do:

masked = image - mask

But I want to "displace" mask. That is, move it vertically and horizontally (as long as the intersection between it and image is not empty, this would be valid).

I have some hand-coded assembly (which uses MMX instructions) which does this, embedded in a C++ program, but it's unstable when doing vertical displacement, so I thought of using OpenCV instead. Would it be possible to do this calling only one OpenCV function?

Performance is critical; using OpenCV, time should be at least in the same order of magnitude as the assembly code.

EDIT: Here's an example

image (medium frame, see the contrast in the guy's skull):

Image

mask (first frame, no contrast):

enter image description here

image - mask, without displacement. Notice how the contrast path is enhanced, but since the patient moved a little, we can see some skull contours which are visual noise for diagnostic purposes.

enter image description here

image - mask, mask displaced about 5 pixels down. To try and compensate for the noise introduced by the patient's movement, we "displace" the mask slightly so as to remove the contours and see the contrast path better (brightness and contrast were adjusted, that's why it looks a bit darker).

enter image description here

EDIT 2: About the algorithm, I managed to fix its issues. It doesn't crash anymore, but the downside is that it now processes all image pixels (it should only process those which need to be subtracted). Anyway, how to fix the old code is not my question; my question is, how do I do this processing using OpenCV? I'll post some profiling results later.

dario_ramos
  • 7,118
  • 9
  • 61
  • 108
  • Can you update your answer with a few more items: 1. Sample input image with a couple of masks "displaced" (i.e., expected output for a given input). 2. Possibly sample code or pseudo-code of what you're doing. 3. How fast your displacement algorithm currently run on a given image size and on what hardware. – mevatron Mar 20 '12 at 21:54
  • This is not [related to this thread](http://stackoverflow.com/questions/9260717/displacement-map-filter-in-opencv), is it? – karlphillip Mar 21 '12 at 01:17
  • @karlphillip: No, that thread is talking about a different effect, which seems more complex than mine, btw. See my example. – dario_ramos Mar 21 '12 at 13:50
  • @mevatron: Done. I'll post some profiling results later. – dario_ramos Mar 21 '12 at 13:51
  • +1 Interesting pictures. – karlphillip Mar 21 '12 at 13:51

1 Answers1

2

I know this is in Python, so not what you are after, but translating it to C++ should be very straight forward. It crops both images to matching sizes (required for nearly all operations), determined by the displacement between the images, and their relative sizes. This method should be quick, as cv.GetSubRect doesn't copy anything, so its just down to the cv.AbsDiff function (if you have an actual difference mask, you could use cv.Sub which should make it even quicker). Also this code will handle displacement in any direction and mask and image can be any size (mask can be larger than image). There must be an overlap for a specified displacement. The difference between images can be viewed alone, or the difference 'in-place'.

A nice diagram to illustrate whats going on. The first two squares are example image and mask. The next three squares show a horizontal displacement of the 'mask' of -30, 0, and 30 pixels, and the last one has a displacement of 20, 20.

enter image description here

import cv

image = cv.LoadImageM("image.png")
mask = cv.LoadImageM("mask.png")

image = cv.LoadImageM("image2.png")
mask = cv.LoadImageM("small_mask.png")

image_width, image_height = cv.GetSize(image)
mask_width, mask_height = cv.GetSize(mask)
#displacements here:
horiz_disp = 20
vert_disp = 20

image_horiz = mask_horiz = image_vert = mask_vert = 0

if vert_disp < 0:
    mask_vert = abs(vert_disp)
    sub_height = min(mask_height + vert_disp, image_height)
else:
    sub_height = min(mask_height, image_height - vert_disp)
    image_vert = vert_disp

if horiz_disp < 0:
    mask_horiz = abs(horiz_disp)
    sub_width = min(mask_width + horiz_disp, image_width)
else:
    sub_width = min(mask_width, image_width - horiz_disp)
    image_horiz = horiz_disp

#cv.GetSubRect returns a rectangular part of an image, without copying any data. - fast.
mask_sub = cv.GetSubRect(mask, (mask_horiz, mask_vert, sub_width, sub_height))
image_sub = cv.GetSubRect(image, (image_horiz, image_vert, sub_width, sub_height))

#Subtracts the mask overlap region from the image overlap region, puts it in image_sub
cv.AbsDiff(image_sub, mask_sub, image_sub)

# Shows diff only:
cv.ShowImage('image_sub', image_sub)
# Shows image with diff section
cv.ShowImage('image', image)

cv.WaitKey(0)
fraxel
  • 34,470
  • 11
  • 98
  • 102
  • Looks good. When I get some free time, I'll profile this against my legacy handcrafted algorithm and post the results. – dario_ramos Mar 21 '12 at 16:43
  • @dario_ramos - just updated to allow displacement in any direction (+pretty picture). And..cool, look forward to hearing about the profiling :) – fraxel Mar 22 '12 at 17:45