Home > other >  Add a cv::Mat inside a cv::Mat at a specific position
Add a cv::Mat inside a cv::Mat at a specific position

Time:02-07

I am currently making a soft that renders chess game. To do it, I use OpenCV. The idea is to have the chess board in a cv::Mat and add pieces with a std::array of 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");
}

And after, I have made a method to try to add a piece in the chess board. I have started by use the copyTo:

cv::Mat RenderImage::getImage() { cv::Mat chess = 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;
}

But I have a black square like around the piece:

image1

So I tryed to make my own methods:

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

And I have changed the methode 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 :

img2

So can you help me to find a solution to draw piece inside my chess board ? Thank you

CodePudding user response:

Thanks you @Christoph Rackwitz, with your link I have found the solution. I convert the python code of Try2Code ( enter link description here )

The final code is here :

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;
}
  •  Tags:  
  • Related