1 | initial version |
Looking at this post: http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
I noticed his following remark
This code only works if:
- The background is in BGR colour space.
- The foreground is in BGRA colour space.
The output image will always be of the same size as the background image, in BGR colour space. The position parameter determines how the foreground is placed on top of the background. A position of (100, -50) will move the foreground 100 pixels to the right and 50 pixels up.
SO I am guessing you cannot read both images as CV_LOAD_IMAGE_UNCHANGED
, which would make both images of type BGRA
.
2 | No.2 Revision |
Looking at this post: http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
I noticed his following remarktaking Max5684 comment
// http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
// https://gist.github.com/maximus5684/082f8939edb6aed7ba0a
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void overlayImage(Mat* src, Mat* overlay, const Point& location)
{
for (int y = max(location.y, 0); y < src->rows; ++y)
{
int fY = y - location.y;
if (fY >= overlay->rows)
break;
for (int x = max(location.x, 0); x < src->cols; ++x)
{
int fX = x - location.x;
if (fX >= overlay->cols)
break;
double opacity = ((double)overlay->data[fY * overlay->step + fX * overlay->channels() + 3]) / 255;
for (int c = 0; opacity > 0 && c < src->channels(); ++c)
{
unsigned char overlayPx = overlay->data[fY * overlay->step + fX * overlay->channels() + c];
unsigned char srcPx = src->data[y * src->step + x * src->channels() + c];
src->data[y * src->step + src->channels() * x + c] = srcPx * (1. - opacity) + overlayPx * opacity;
}
}
}
}
int main( int argc, char** argv )
{
Mat underlay = imread("14447300874345549.png",IMREAD_UNCHANGED);
Mat overlay = imread("14447300692773615.png",IMREAD_UNCHANGED);
Mat test = imread("1429209553641108.png",IMREAD_UNCHANGED);
if( underlay.empty() || overlay.empty() || test.empty() )
{
cout << "Could not read input image files " << endl;
return -1;
}
overlayImage( &underlay, &overlay, Point() );
overlayImage( &test, &underlay, Point(120,180) );
imwrite("result.png",test);
imshow("result",test);
waitKey();
return 0;
}
Test Images :
Result Image:
This code only works if:
- The background is in BGR colour space.
- The foreground is in BGRA colour space.
The output image will always be of the same size as the background
image, in BGR colour space.image. The position parameter determines how the foreground is placed on top of the background. A position of (100, -50) will move the foreground 100 pixels to the right and 50 pixels up.
SO I am guessing you cannot read both images as CV_LOAD_IMAGE_UNCHANGED
, which would make both images of type BGRA
.
3 | No.3 Revision |
Looking at this post: http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
taking Max5684 comment
// http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
// https://gist.github.com/maximus5684/082f8939edb6aed7ba0a
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void overlayImage(Mat* src, Mat* overlay, const Point& location)
{
for (int y = max(location.y, 0); y < src->rows; ++y)
{
int fY = y - location.y;
if (fY >= overlay->rows)
break;
for (int x = max(location.x, 0); x < src->cols; ++x)
{
int fX = x - location.x;
if (fX >= overlay->cols)
break;
double opacity = ((double)overlay->data[fY * overlay->step + fX * overlay->channels() + 3]) / 255;
for (int c = 0; opacity > 0 && c < src->channels(); ++c)
{
unsigned char overlayPx = overlay->data[fY * overlay->step + fX * overlay->channels() + c];
unsigned char srcPx = src->data[y * src->step + x * src->channels() + c];
src->data[y * src->step + src->channels() * x + c] = srcPx * (1. - opacity) + overlayPx * opacity;
}
}
}
}
int main( int argc, char** argv )
{
Mat underlay = imread("14447300874345549.png",IMREAD_UNCHANGED);
Mat overlay = imread("14447300692773615.png",IMREAD_UNCHANGED);
Mat test = imread("1429209553641108.png",IMREAD_UNCHANGED);
if( underlay.empty() || overlay.empty() || test.empty() )
{
cout << "Could not read input image files " << endl;
return -1;
}
overlayImage( &underlay, &overlay, Point() );
);
overlayImage( &test, &underlay, Point(120,180) );
imwrite("result.png",test);
imshow("result",test);
imwrite("result1.png",underlay);
imwrite("result2.png",test);
imshow("result1",underlay);
imshow("result2",test);
waitKey();
return 0;
}
Test Images :
Result Image:Images:
The output image will always be of the same size as the background image. The position parameter determines how the foreground is placed on top of the background. A position of (100, -50) will move the foreground 100 pixels to the right and 50 pixels up.
4 | No.4 Revision |
Looking at this post: http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
taking Max5684 comment
// http://jepsonsblog.blogspot.be/2012/10/overlay-transparent-image-in-opencv.html
// https://gist.github.com/maximus5684/082f8939edb6aed7ba0a
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void overlayImage(Mat* src, Mat* overlay, const Point& location)
{
for (int y = max(location.y, 0); y < src->rows; ++y)
{
int fY = y - location.y;
if (fY >= overlay->rows)
break;
for (int x = max(location.x, 0); x < src->cols; ++x)
{
int fX = x - location.x;
if (fX >= overlay->cols)
break;
double opacity = ((double)overlay->data[fY * overlay->step + fX * overlay->channels() + 3]) / 255;
for (int c = 0; opacity > 0 && c < src->channels(); ++c)
{
unsigned char overlayPx = overlay->data[fY * overlay->step + fX * overlay->channels() + c];
unsigned char srcPx = src->data[y * src->step + x * src->channels() + c];
src->data[y * src->step + src->channels() * x + c] = srcPx * (1. - opacity) + overlayPx * opacity;
}
}
}
}
int main( int argc, char** argv )
{
Mat underlay = imread("14447300874345549.png",IMREAD_UNCHANGED);
Mat overlay = imread("14447300692773615.png",IMREAD_UNCHANGED);
Mat test = imread("1429209553641108.png",IMREAD_UNCHANGED);
if( underlay.empty() || overlay.empty() || test.empty() )
{
cout << "Could not read input image files " << endl;
return -1;
}
Mat rgba[4];
split(underlay,rgba);
imshow("alpha1.png",rgba[3]);
imwrite("alpha1.png",rgba[3]);
split(overlay,rgba);
imshow("alpha2.png",rgba[3]);
imwrite("alpha2.png",rgba[3]);
overlayImage( &underlay, &overlay, Point() );
);
overlayImage( &test, &underlay, Point(120,180) );
imwrite("result1.png",underlay);
split(underlay,rgba);
imshow("alpha3.png",rgba[3]);
imwrite("alpha3.png",rgba[3]);
imshow("result1",underlay);
imwrite("result1.png",underlay);
imshow("result2",test);
imwrite("result2.png",test);
imshow("result1",underlay);
imshow("result2",test);
waitKey();
return 0;
}
Test Images :
Result Images:
Alpha channels before:
Alpha channel of result:
The output image will always be of the same size as the background image. The position parameter determines how the foreground is placed on top of the background. A position of (100, -50) will move the foreground 100 pixels to the right and 50 pixels up.