7

I want to place an image on a captured video frame at the coordinates which I determined.

I asked that before and I have been told to use cvCopy and cvSetImageROI but I dont want to crop on those coordinates I want to add another image. Maybe it's the right way but I didn't understand it (if its right please explain it).

evotopid
  • 5,288
  • 2
  • 26
  • 41
eomer
  • 3,514
  • 7
  • 30
  • 42

4 Answers4

7

I did this a while ago using SetRoi, it was something like this. I have two images, one is a thumbnail called thumb_frame that is the small picture I will include in the large image show_frame

//I set the ROI to the same size as the thumb_frame
cvSetImageROI(show_frame.image, cvRect(thumbnail_x_pos,
                    thumbnail_y_pos, thumb_frame->width, thumb_frame->height));

//I add the image to the designated ROI
cvAddWeighted(thumb_frame, alpha, show_frame, beta, 0, show_frame);

That's about it.

Ola
  • 477
  • 3
  • 4
6
void cvOverlayImage(IplImage* src, IplImage* overlay, CvPoint location, CvScalar S, CvScalar D)
{
 int x,y,i;

  for(x=0;x < overlay->width -10;x++)     
//replace '-10' by whatever x position you want your overlay image to begin. 
//say '-varX'
    {
        if(x+location.x>=src->width) continue;
        for(y=0;y < overlay->height -10;y++)  
//replace '-10' by whatever y position you want your overlay image to begin.
//say '-varY'
        {
            if(y+location.y>=src->height) continue;
            CvScalar source = cvGet2D(src, y+location.y, x+location.x);
            CvScalar over = cvGet2D(overlay, y, x);
            CvScalar merged;
            for(i=0;i<4;i++)
            merged.val[i] = (S.val[i]*source.val[i]+D.val[i]*over.val[i]);
            cvSet2D(src, y+location.y, x+location.x, merged);
        }
    }
}

To use it

cvOverlayImage(largerimage, overlayimage, cvPoint(10, 10), cvScalar(0.5,0.5,0.5,0.5), cvScalar(0.5,0.5,0.5,0.5)); 
//The cvPoint(10,10) can be the cvPoint(varX,varY) depending on how you write the function 
//and how you want to use it. 
//You cannot choose values less than 'varX' and 'varY' in this case
//else you would see a runtime error.
enthusiasticgeek
  • 2,640
  • 46
  • 53
  • Thanks George. I really can't figure out how to use the editing tools here. I can write complicated code yet can't do these simple things :). What did you use to highlight my code. I tried
     and 
    – enthusiasticgeek Aug 10 '10 at 14:14
  • Hey with this solution if the overlay image has a very large width and height it doesnt crop the image right ! Could you suggest some method where the overlay image is rescaled and fit to the fixed area. – Pavan K Apr 03 '12 at 22:23
  • @PavanK how about using cvResize() if rescaling whole image? , if you want to use a part of image and resize that part you would have to set ROI, copy, scale, reset ROI. Take a look at an example here http://nashruddin.com/OpenCV_Region_of_Interest_(ROI) [copy and paste link - including brackets, else won't work] – enthusiasticgeek Apr 04 '12 at 20:39
  • @enthusiasticgeek Yes I tried that approach and it works well only for rectangles. Is there any way to fit it in a polygon with 4 vertices? I tried to use warp_matrix but didn't quite work well. My question is here http://stackoverflow.com/questions/9997544/overlay-smaller-image-in-a-larger-image-in-opencv/10016356 – Pavan K Apr 05 '12 at 09:55
  • @PavanK Can you not apply a mask like the following example? http://nashruddin.com/OpenCV_Circular_ROI – enthusiasticgeek Apr 05 '12 at 18:53
  • updated link http://stackoverflow.com/questions/10632195/define-image-roi-with-opencv-in-c – enthusiasticgeek Apr 25 '14 at 12:16
0

Unfortunately the "Paul Lammertsma" code has mixed up indexes here you have fixed code:

void drawImage(IplImage* target, IplImage* source, int x, int y) {

    for (int ix=0; ix<source->width; ix++) {
        for (int iy=0; iy<source->height; iy++) {
            int r = cvGet2D(source, iy, ix).val[2];
            int g = cvGet2D(source, iy, ix).val[1];
            int b = cvGet2D(source, iy, ix).val[0];
            CvScalar bgr = cvScalar(b, g, r);
            cvSet2D(target, iy+y, ix+x, bgr);
        }
    }
}
Michał Jankowski
  • 407
  • 1
  • 6
  • 16
0

You will have to copy pixel by pixel from the source to the destination. The code below does precisely that, offseting with coordinates x and y. I haven't actually tried this, but am fairly certain it should work more or less as you'd expect.

Just make sure the target image is at least the size of the source plus the offset!

void drawImage(IplImage* target, IplImage* source, int x, int y) {
    for (int ix=0; x<source->width; x++) {
        for (int iy=0; y<source->height; y++) {
            int r = cvGet2D(source, iy, ix).val[2];
            int g = cvGet2D(source, iy, ix).val[1];
            int b = cvGet2D(source, iy, ix).val[0];
            CvScalar bgr = cvScalar(b, g, r);
            cvSet2D(target, iy+y, ix+x, bgr);
        }
    }
}
Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
  • thanks but i want to combine all of the source to x,y pixels of the target i think i must add 2 for loops to your code the for loops in your code will get the r,g,b values of the source and the other 2 i will add will change the targets rgb is it correct – eomer Oct 19 '09 at 10:53
  • The above code will cycle through all the pixels of the source image and copy them one by one to an offset position on the target image. There is no need for any additional loops unless you intend to copy multiple `IplImage`s onto the target. – Paul Lammertsma Oct 19 '09 at 14:50
  • ok i undertand your code thanks i already have a loop for multiple image i think you didnt understand me i want to do exactly opposite of your code what i want to do is replace a part of my source image with another image – eomer Oct 20 '09 at 06:06
  • Simply swap the `IplImage`s in the parameters to accomplish that. In essence what you need to do, is take the captured video as `target`, an image you want to overlay as `source`, and specify the `x` and `y` offset where you want the image placed on the video. Since the target video is passed with a pointer, you can then proceed to process the captured video frame after calling `drawImage()`. – Paul Lammertsma Oct 20 '09 at 10:13
  • paul i just use your code before your last comment i replace targets and sources with each other in the code however the image i want to put is put but on another coordinates and lenghten widely i want to put it on my eye detection program i put a black image to eyes but instead of eyes it appeared on the forhead if you want i can sen you the code – eomer Oct 20 '09 at 11:41
  • @eomer I've received your e-mail, but don't mind if I respond here. There's a simpler way of copying images pixel-by-pixel. The previous code was specific to three-channel images. I've updated my code accordingly. Give it a swing and let me know if it works or not. – Paul Lammertsma Jan 24 '10 at 00:41
  • Thats not fast. You can improve by using `real` get/set functions, better use @Ola's code. – Cfr Jul 26 '10 at 08:30