大纲
本程序希望解决的问题是大学中社团外联常见的扩散要求,即需要为赞助商的产品发朋友圈,同学找到你让你转发的时候又不好直接拒绝,就可以通过个办法伪造一下朋友圈截图。注:自己拉的外联的话该转发还是转发吧,人家毕竟给了钱。。。
实现思路
给定两张朋友圈截图,一张包含自己发的朋友圈以从中提取头像区域;一张为其他人转发的含推广内容的朋友圈,将前一张的头像提取到后一张头像区域,或者将后一张的推广区域覆盖到前一张内容区域即完成了目标。
使用opencv实现的话就是为两张图片分别开辟两个窗口,在source窗口中框选出要提取的区域,在product区域左击要覆盖区域的左上角,自动将前述提取区域覆盖至此,由于手机截图的分辨率一般较大,无法在窗口中完全显示,所以预先resize到了固定大小。
代码如下:
#include<opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
#define MAX_HEIGHT 800
void ROI_linearBlending(Mat srcImg_1, Mat srcImg_2, string saving_path);
void MouseCall(int event, int x, int y, int flag, void* paramas);
void ROI(int event, int x, int y, int flag, void* paramas);
void DrawRect(Mat& img, Rect box);
int width = 0, height = 0;
bool drawbox = false;
Rect _rectangle;
Rect source_rect, product_rect;
int main()
{
string img_path1;
string img_path2;
string save_path;
cout <<"input source_img path:\n";
cin >> img_path1;
cout << "input dest_img path:\n";
cin >> img_path2;
cout << "input saving path:\n";
cin >> save_path;
Mat srcImg_1 = imread(img_path1);
Mat srcImg_2 = imread(img_path2);
cout << "shape of first imag:(" << srcImg_1.rows << ',' << srcImg_1.cols << ')' << endl;
cout << "shape of first imag:(" << srcImg_2.rows << ',' << srcImg_2.cols << ')' << endl;
float ratio1 = float(srcImg_1.cols) / srcImg_1.rows;
float ratio2 = float(srcImg_2.cols) / srcImg_2.rows;
Mat tempImg1, tempImg2;
Mat showImg1, showImg2;
if (srcImg_1.rows > MAX_HEIGHT)
resize(srcImg_1, showImg1, Size(int(MAX_HEIGHT * ratio1),MAX_HEIGHT ));
else
srcImg_1.copyTo(showImg1);
if (srcImg_2.rows > MAX_HEIGHT)
resize(srcImg_2, showImg2, Size(int(MAX_HEIGHT * ratio2),MAX_HEIGHT));
else
srcImg_2.copyTo(showImg2);
showImg2.copyTo(tempImg2);
namedWindow("source", WINDOW_AUTOSIZE);
namedWindow("product", WINDOW_AUTOSIZE);
namedWindow("dst", WINDOW_AUTOSIZE);
setMouseCallback("source", MouseCall, &showImg1);
setMouseCallback("product", ROI, &showImg2);
while (true)
{
char c = waitKey(10);
if (c == 'q')
{
break;
}
showImg1.copyTo(tempImg1);
if (drawbox)
{
DrawRect(tempImg1, _rectangle);//绘制标识符为真时,画矩形
}
imshow("source", tempImg1);//注意,这里显示的图片以及上一张画图的图片都是tempImg,即只显示拖动每一刻的矩形,不累计
imshow("product", showImg2);
}
ROI_linearBlending(tempImg1, tempImg2,save_path);
while (waitKey(10) != ' ');
}
void ROI_linearBlending(Mat srcImg_1, Mat srcImg_2,string saving_path)
{
Mat imgROI1, imgROI2, temp1, temp2, dst;
srcImg_1.copyTo(temp1);
srcImg_2.copyTo(temp2);
imgROI1 = temp1(source_rect);
imgROI2 = temp2(product_rect);
addWeighted(imgROI1, 1., imgROI2, 0., 0., imgROI2);
imshow("dst", temp2);
imwrite(saving_path, temp2);
}
void MouseCall(int event, int x, int y, int flag, void* paramas)
{
Mat tempimg1;
Point end, now;
static Point start = Point(-1, -1);
tempimg1 = Mat(*(Mat*)paramas);
if (event == EVENT_MOUSEMOVE)
{
if (drawbox)
{
now = Point(x, y);
}
}
if (event == EVENT_LBUTTONDOWN)
{
start = Point(x, y);
drawbox = true;
}
if (event == EVENT_LBUTTONUP)
{
end = Point(x, y);
width = end.x - start.x > 0 ? end.x - start.x : start.x - end.x;
height = end.y - start.y > 0 ? end.y - start.y : start.y - end.y;
source_rect = Rect(start, end);
//DrawRect(tempimg1,source_rect);
drawbox = false;
}
_rectangle = Rect(start, now);
}
void DrawRect(Mat& img, Rect box)
{
RNG& rng = theRNG();
rectangle(img, box.tl(), box.br(), Scalar(rng.uniform(0, 255),
rng.uniform(0, 255), rng.uniform(0, 255))); //以(0,255)内均匀随机数作为矩形颜色
}
void ROI(int event, int x, int y, int flag, void* paramas)
{
Mat temp;
bool l_drawbox = false;
temp = *(Mat*)paramas;
if (event == EVENT_LBUTTONDOWN)
{
product_rect = Rect(x, y, width, height);
l_drawbox = true;
}
if (l_drawbox)
DrawRect(temp, product_rect);
}
输入图片source:
输入图片product:
结果图: