Используйте OpenCV для реализации аватара градиентной версии Национального дня.

машинное обучение искусственный интеллект алгоритм

Во время Национального дня я обнаружил, что аватары многих друзей изменились, добавив эффект национального флага, сделав его более праздничным.

Эффект не выглядит сложным, и его можно добиться с помощью десятков строк OpenCV.

Простейший вариант слияния изображений

Начнем с самого простого варианта слияния изображений, найдем аватарку и изображение стандартного национального флага и обрежем найденную аватарку до размера национального флага.

icon.jpg

Затем два изображения накладываются друг на друга.

    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);

roi.png

Градиентная версия

Эффект только что общий, тогда давайте попробуем снова градиентную версию. Чем ближе вы к красному флагу, тем больше вес красного флага. Таким образом можно добиться эффекта градиента.

    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);

result.png

Эффект в этот раз намного лучше, чем в первый раз :). Кстати, я желаю вам всем счастливого Национального дня!