Использование изображения PNG в качестве маски для GrabCut
У меня есть png-изображение с зелеными и красными линиями и прозрачным фоном, которое мне нужно использовать в качестве маски для выполнения GrabCut. Но я получаю неожиданные результаты. Вот мой код:
//find the mask
Mat mask;
mask.create( image.size(), CV_8UC1);
mask.setTo(Scalar::all(GC_BGD));
Mat maskImg = imread("messi5.png");
for(int i=0; i<maskImg.cols; i++)
for(int j=0; j<maskImg.rows; j++)
{
//if it's red, make it white
if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 0 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 255) {
mask.at<cv::Vec3b>(j,i)[0]= GC_BGD;
mask.at<cv::Vec3b>(j,i)[1] = GC_BGD;
mask.at<cv::Vec3b>(j,i)[2] = GC_BGD;
}
//if it's green, make it black
if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 255 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 0) {
mask.at<cv::Vec3b>(j,i)[0] = GC_FGD;
mask.at<cv::Vec3b>(j,i)[1] = GC_FGD;
mask.at<cv::Vec3b>(j,i)[2] = GC_FGD;
}
}
...
Вот результат: http://prntscr.com/40kt4e . я думаю, что это похоже на то, что нет прямоугольника, он видит только пиксели GC_FGD, все остальное считается BG. И это выглядит как-то масштабировано, но я понятия не имею, как это исправить.
1 ответ:
Я пытался сказать в
GrabCut маска чтения из файла PNG в OpenCV (C++)
Что вы используете 3-канальный аксессор для 1-канального изображения. это немного все испортит, используйте версию 1 канала для маски 1 канала:
Mat image; image= cv::imread(file); //everything outside this box will be set to def. //background GC_BGD, clearly from the image you can see that the players legs are outside the box, //so this will cause problems. you need to either change the box, //such that everything is outside the box is the background, or use your mask to scribble on the players legs in green. cv::Rect rectangle(startX, startY, width, height); cv::Mat bgModel,fgModel; //find the mask Mat mask; mask.create( image.size(), CV_8UC1); //CV_8UC1 is single channel mask.setTo(Scalar::all(GC_BGD)); //you have set it to all def. background Mat maskImg = imread("messi5.png"); for(int i=0; i<maskImg.cols; i++) for(int j=0; j<maskImg.rows; j++) { //if it's red, make it black if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 0 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 255) { //the whole mask is black so this is redundant mask.at<uchar>(j,i)= GC_BGD; //GC_BGD := 0 := black } //if it's green, make it white if ((int)maskImg.at<cv::Vec3b>(j,i)[0]==0 && (int)maskImg.at<cv::Vec3b>(j,i)[1] == 255 && (int)maskImg.at<cv::Vec3b>(j,i)[2] == 0) { mask.at<uchar>(j,i) = GC_FGD; //GC_FGD:= 1 := white } }
Для более эффективного кода для циклического перебора изображений см.: http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html
Функция LUT my делает трюк здесь: http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#the-core-function