Я не уверен, что вы имеете в виду, когда говорите «мой результат не достаточно хорош». Лучше посмотреть этот результат, но я постараюсь угадать. Моя основная часть кода, что делает панораму, выглядит следующим образом:
void makePanorama(Rect bounding_box, vector<Mat> images, vector<Mat> homographies, vector<vector<Point>> corners) {
detail::MultiBandBlender blender;
blender.prepare(bounding_box);
Mat mask, bigImage, curImage;
for (int i = 0; i < (int)images.size(); ++i) {
warpPerspective(images[i], curImage, homographies[i],
bounding_box.size(), INTER_LINEAR, ORDER_TRANSPARENT);
mask = makeMask(curImage.size(), corners[i], homographies[i]);
blender.feed(curImage.clone(), mask, Point(0, 0));
}
blender.blend(bigImage, mask);
bigImage.convertTo(bigImage, (bigImage.type()/8) * 8);
imshow("Result", bigImage);
waitKey();
}
Таким образом, подготовить blender
, а затем цикл: искривления изображения, сделать маску после искривленного изображения и подачи блендере. В конце, включите этот блендер, и все. Я встретил две проблемы, которые плохо влияют на мой результат. Может быть, у вас есть один из них или оба.
Первый тип. У моих изображений был CV_16SC3, и после смешивания вам нужно преобразовать смешанный тип изображения в unsigned
. Нравится
bigImage.convertTo(bigImage, (bigImage.type()/8) * 8);
Если вы этого не сделали, результат будет серым.
Второй - это границы. В начале моя функция makeMask вычисляла нечерную область искаженных изображений. В результате, на смешанном изображении можно увидеть границы искаженных изображений. Решение состоит в том, чтобы сделать маску меньшей, чем область без черных искажений. Таким образом, моя функция makeMask
это выглядит следующим образом:
Mat makeMask(Size sz, vector<Point2f> imageCorners, Mat homorgaphy) {
Scalar white(255, 255, 255);
Mat mask = Mat::zeros(sz, CV_8U);
Point2f innerPoint;
vector<Point2f> transformedCorners(4);
perspectiveTransform(imageCorners, transformedCorners, homorgaphy);
// Calculate inner point
for (auto& point : transformedCorners)
innerPoint += point;
innerPoint.x /= 4;
innerPoint.y /= 4;
// Make indent for each corner
vector<Point> corners;
for (int ind = 0; ind < 4; ++ind) {
Point2f direction = innerPoint - transformedCorners[ind];
double normOfDirection = norm(direction);
corners[ind].x += settings.indent * direction.x/normOfDirection;
corners[ind].y += settings.indent * direction.y/normOfDirection;
}
// Draw borders
Point prevPoint = corners[3];
for (auto& point : corners) {
line(mask, prevPoint, point, white);
prevPoint = point;
}
// Fill with white
floodFill(mask, innerPoint, white);
return mask;
}
Я взял эти куски кода из моего реального кода, так что я мог забыть указать что-то. Но я надеюсь, что идея о том, как работать с MultiBandBlender
, понятна.
Без фактического примера вам сложно помочь. –