I build a watermark creator by OpenCV. The program could create watermark in the 4 corner of a source image. I haven't change the source image direction and the output image is also copied from the merge of source image and watermark. When I make a test, a image was rotated and the watermark was in the incorrect place. However when I use the thumbnail of that image for test, the direction is correct. So I guess the problem is in the size of image.
Here is my code.
#include "test.h"
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
#define LEFT_TOP 0
#define LEFT_DOWN 1
#define MIDDLE 2
#define RIGHT_TOP 3
#define rIGHT_DOWN 4
//watermark position offset
#define off_ratio 40
//the ratio of watermark and the source image
#define length_ratio 6
int main_test(int argc , char * argv[])
{
//Read from alpha channel ,Transparent
Mat img_src = imread(argv[1], CV_LOAD_IMAGE_UNCHANGED);
cout << (int)img_src.at<Vec4b>(0,0)[0] << endl
<< (int)img_src.at<Vec4b>(0,0)[1] << endl
<< (int)img_src.at<Vec4b>(0,0)[2] << endl
<< (int)img_src.at<Vec4b>(0,0)[3] << endl;
cout << (int)img_src.at<Vec4b>(10,10)[0] << endl
<< (int)img_src.at<Vec4b>(10,10)[1] << endl
<< (int)img_src.at<Vec4b>(10,10)[2] << endl
<< (int)img_src.at<Vec4b>(10,10)[3] << endl;
return 0;
}
int add_watermask(Mat & img_roi, Mat img_water_mask, float scale_ratio)
{
vector<Mat>src_channels;
vector<Mat>watermark_channels;
//Split the channel
split(img_roi, src_channels);
split(img_water_mask, watermark_channels);
if (scale_ratio < 1)
{
watermark_channels[3] *= scale_ratio;
scale_ratio = 1;
}
for (int i = 0; i < 3; i++)
{
//dstt_channels[i] = dstt_channels[i].mul(255.0 / scale - scr_channels[3], scale / 255.0);
//dstt_channels[i] += scr_channels[i].mul(scr_channels[3], scale / 255.0);
src_channels[i] = src_channels[i].mul(255.0 / scale_ratio - watermark_channels[3], scale_ratio / 255.0);
src_channels[i] += watermark_channels[i].mul(watermark_channels[3], scale_ratio / 255.0);
}
merge(src_channels, img_roi);
return 0;
}
//Calculate the watermark position in the source image
int process_pose(Mat & src, Mat & water, Mat & roi, Mat & water_resize, int pose)
{
int width_src = src.cols;
int height_src = src.rows;
int width_water = water.cols;
int height_water = water.rows;
int max_length_src = max(width_src, height_src);
//5% offset of the image length
int off = max_length_src / off_ratio;
//Watermark length is 1/6 of the source image
int length_1_6 = max_length_src / length_ratio;
int scale_width_water = length_1_6;
int scale_height_water = length_1_6 * height_water / width_water;
//if the source image width larger than height,then keep the scale of watermark's height and source image' height
if(width_src > height_src) {
if ((off * 2 + scale_height_water) > height_src) {
off = height_src / off_ratio;
scale_height_water = height_src / length_ratio;
scale_width_water = scale_height_water * width_water / height_water;
}
}
//if the source image height larger than width,then keep the scale of watermark's width and source image' width
else{
if((off * 2 + scale_width_water) > width_src)
{
off = width_src / off_ratio;
scale_width_water = width_src / length_ratio;
scale_height_water = scale_width_water * height_water / width_water;
}
}
int ret = 0 ;
Rect pose_water = {0,0,0,0};
pose_water.width = scale_width_water;
pose_water.height = scale_height_water;
switch(pose)
{
case 0:
pose_water.x = off;
pose_water.y = off;
break;
case 1:
pose_water.x = off;
pose_water.y = height_src - off - scale_height_water;
break;
case 2:
pose_water.x = (width_src - scale_width_water)/2;
pose_water.y = (height_src - scale_height_water)/2;
break;
case 3:
pose_water.x = width_src - scale_width_water - off;
pose_water.y = off;
break;
case 4:
pose_water.x = width_src - scale_width_water - off;
pose_water.y = height_src - scale_height_water - off;
break;
default:
printf("wrong pose
");
ret = -1;
break;
}
if(ret == -1)
{
return ret;
}
roi = src(pose_water);
resize(water, water_resize, Size(scale_width_water, scale_height_water));
return 0;
}
int main(int argc , char * argv[])
{
if(argc < 6)
{
cout << "used error
";
cout <<"used follow: " << argv[0] << " img1(jpg) img2(png) Tranparacy(0-100) Position(LEFT_TOP(0), LEFT_DOWN(1), MIDDLE(2), RIGHT_TOP(3),RIGHT_DOWN(4)), the result
";
cout << "example: /home/disk/0_raw.jpg /home/disk/logo.png 0 0 /home/disk/logo_0_test.jpg
";
return 103;
}
Mat img_src = imread(argv[1]);
Mat img_water_mark = imread(argv[2], -1);
//Check the argument
if(img_src.data == NULL || img_water_mark.data == NULL)
{
cout << "read img failed check it
"
<< "img1: " << argv[1] << endl
<< "img1: " << argv[1] << endl;
return 101;
}
//Grey convert to color
if(img_src.channels() != 3)
{
cvtColor(img_src, img_src, COLOR_GRAY2BGR);
}
//Check the channel is correct
if(img_src.channels() != 3 || img_water_mark.channels() != 4)
{
cout << "img 's channnel is error ,check it
";
return 102;
}
//Default watermark width is larger than height
if(img_water_mark.cols < img_water_mark.rows)
{
cout << "Watermark height large than width, check it
";
return 104;
}
//Transparency(0-100)
int scale = atoi(argv[3]);
float scale_ratio = (1- scale / 100.0);
if (scale_ratio > 1.0 || scale_ratio < 0.0)
{
cout << "scale is error , put scale in 1~100
";
return 105;
}
int pose = atoi(argv[4]);
Mat src_copy = img_src.clone();
Mat water_copy = img_water_mark.clone();
Mat roi, water_resize ;
int ret = process_pose(src_copy, water_copy, roi, water_resize, pose);
if(ret == -1)
{
printf("other pose not in LEFT_TOP(0), LEFT_DOWN(1), MIDDLE(2), RIGHT_TOP(3),RIGHT_DOWN(4), check it
");
return 106;
}
// Mat img_roi(img_src, cvRect(0, 0, img_water_mark.cols, img_water_mark.rows));
// add_watermask(img_roi, img_water_mark, scale_ratio);
add_watermask(roi, water_resize, scale_ratio);
//imshow("img", src_copy);
imwrite(argv[5], src_copy);
//waitKey();
return 0;
}
I want to create a watermark in the RIGHT_DOWN position of the image, but the output image was rotated. So the watermark position is wrong.
Due to the limit of stackoverflow I can only upload a image less than 2MB. The original source image is 6MB. Here is the thumbnail of the source image.
Here is the thumbnail of the original source image output.
Caution: When I use the thumbnail of original image as input, the result is correct.
Here is the output when I use thumbnail of source image as input.
See Question&Answers more detail:
os