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