Во время Национального дня я обнаружил, что аватары многих друзей изменились, добавив эффект национального флага, сделав его более праздничным.
Эффект не выглядит сложным, и его можно добиться с помощью десятков строк OpenCV.
Простейший вариант слияния изображений
Начнем с самого простого варианта слияния изображений, найдем аватарку и изображение стандартного национального флага и обрежем найденную аватарку до размера национального флага.
Затем два изображения накладываются друг на друга.
cv::Mat image = cv::imread("/Users/tony/Downloads/icon.jpg");
cv::Mat flag = cv::imread("/Users/tony/Downloads/flag.png");
cv::Mat roi,dst;
cv::imshow("image",image);
cv::imshow("flag",flag);
roi = image(cv::Rect(300,400, flag.cols, flag.rows));
cv::addWeighted(roi, 0.8, flag, 0.35, 0, dst);
cv::imshow("dst",dst);
Градиентная версия
Эффект только что общий, тогда давайте попробуем снова градиентную версию. Чем ближе вы к красному флагу, тем больше вес красного флага. Таким образом можно добиться эффекта градиента.
cv::Mat image = cv::imread("/Users/tony/Downloads/icon.jpg");
cv::Mat flag = cv::imread("/Users/tony/Downloads/flag.png");
int flag_width = flag.cols;
int flag_height = flag.rows;
Mat roi = image(cv::Rect(450,1200, flag_width, flag_height));
int radius = 0;
if (flag_width > flag_height) {
radius = flag_width;
} else {
radius = flag_height;
}
for (int i=0; i<roi.rows; i++) {
for (int j=0;j<roi.cols;j++) {
int distance = std::sqrt(i*i+j*j);
double alpha;
if (distance > radius) {
alpha = 1;
} else {
alpha = (double) distance / radius;
}
Vec3b v1 = roi.at<Vec3b>(i,j);
roi.at<Vec3b>(i,j)[0]=alpha*v1[0] + (1-alpha)*flag.at<Vec3b>(i,j)[0];
roi.at<Vec3b>(i,j)[1]=alpha*v1[1] + (1-alpha)*flag.at<Vec3b>(i,j)[1];
roi.at<Vec3b>(i,j)[2]=alpha*v1[2] + (1-alpha)*flag.at<Vec3b>(i,j)[2];
}
}
cv::imshow("dst",roi);
Эффект в этот раз намного лучше, чем в первый раз :). Кстати, я желаю вам всем счастливого Национального дня!