在特定位置的 cv::Mat 内添加 cv::Mat

Add a cv::Mat inside a cv::Mat at a specific position

我目前正在制作一个渲染国际象棋游戏的软件。为此,我使用 OpenCV。 这个想法是将棋盘放在 cv::Mat 中,并添加 std::array 为 cv::Mat 的棋子:

RenderImage::RenderImage() { 
    backgroundChess = cv::imread("files/board_chess4.png"); /// The chess board

    piecesChess[0] = cv::imread("files/pieces/wP.png"); /// The pieces
    piecesChess[1] = cv::imread("files/pieces/wB.png");
    piecesChess[2] = cv::imread("files/pieces/wN.png");
    piecesChess[3] = cv::imread("files/pieces/wR.png");
    piecesChess[4] = cv::imread("files/pieces/wQ.png");
    piecesChess[5] = cv::imread("files/pieces/wK.png");

    piecesChess[6] = cv::imread("files/pieces/bP.png");
    piecesChess[7] = cv::imread("files/pieces/bB.png");
    piecesChess[8] = cv::imread("files/pieces/bN.png");
    piecesChess[9] = cv::imread("files/pieces/bR.png");
    piecesChess[10] = cv::imread("files/pieces/bQ.png");
    piecesChess[11] = cv::imread("files/pieces/bK.png");
}

后来,我做了一个尝试在棋盘上加棋子的方法。 我已经开始使用 copyTo:

cv::Mat RenderImage::getImage() { cv::Mat 国际象棋 = backgroundChess.clone();

    piecesChess[0].copyTo(chess(cv::Rect(0,0, piecesChess[0].cols, piecesChess[0].rows)));

    cv::imshow("Display Image", chess);


    cv::waitKey(0);

    return chess;
}

但我的作品周围有一个黑色方块:

所以我尝试了自己的方法:

void RenderImage::merge2img(cv::Mat& back, const cv::Mat front, std::size_t posX, std::size_t posY) {
    cv::Size bsize { back.size() };
    cv::Size fsize { front.size() };


    for (std::size_t startX {posX}; startX < posX + fsize.width && startX < bsize.width; startX++) {
        for (std::size_t startY {posY}; startY < posY + fsize.height && startY < bsize.height; startY++) {
            cv::Vec4b fpixel { front.at<cv::Vec4b>(startY, startX) };
            cv::Vec4b bpixel { back.at<cv::Vec4b>(startY, startX) };

            for (int i {0}; i < 3; i++) {
                back.at<cv::Vec4b>(startY, startX)[i] = (fpixel[i] * fpixel[3] + bpixel[i] * (255 - fpixel[3])) / 255;
            }

            back.at<cv::Vec4b>(startY, startX)[3] = 255;
        }
    }
}

并且我更改了方法 getImage()

cv::Mat RenderImage::getImage() {
    cv::Mat chess = backgroundChess.clone();

    //addWeighted( piecesChess[0], 0.5, backgroundChess, 0.5, 0.0, chess);
    merge2img(chess, piecesChess[0], 0, 0);
    
    //piecesChess[0].copyTo(chess(cv::Rect(0,0, piecesChess[0].cols, piecesChess[0].rows)));

    cv::imshow("Display Image", chess);
    //cv::imshow("Display Image", piecesChess[0]);

    cv::waitKey(0);

    return chess;
}

But the result have this problem :

所以你能帮我找到一个在我的棋盘里画棋子的解决方案吗? 谢谢

谢谢你@Christoph Rackwitz,你 link 我找到了解决方案。 我转换 Try2Code ( enter link description here )

的 python 代码

最终代码在这里:

void RenderImage::overlayImage(cv::Mat& back, const cv::Mat& front, std::size_t posX, std::size_t posY) {
    cv::Mat gray, mask, mask_inv, back_bg, front_bg, result;

    cv::Size fsize { front.size() };

    cv::cvtColor(front, gray, cv::COLOR_BGR2GRAY);

    cv::threshold(gray, mask, 0, 255, cv::THRESH_BINARY);
    cv::bitwise_not(mask, mask_inv);

    cv::Mat roi { back(cv::Range(posX, posX + fsize.width), cv::Range(posY, fsize.height)) };

    cv::bitwise_and(roi, roi, back_bg, mask_inv);
    cv::bitwise_and(front, front, front_bg, mask);

    cv::add(back_bg, front_bg, result);

    cv::addWeighted(roi, 0.1, result, 0.9, 0.0, result);

    result.copyTo(back(cv::Rect(posX, posY, fsize.width, fsize.height)));
}

cv::Mat RenderImage::getImage() {
    cv::Mat chess = backgroundChess.clone();

    overlayImage(chess, piecesChess[0], 128, 0); //The method to merge two images
    cv::imshow("Display Image", chess);

    cv::waitKey(0);

    return chess;
}