如何在OpenCV中使用多波段搅拌机

How to use Multi-band Blender in opencv

本文关键字:多波段 搅拌机 OpenCV      更新时间:2023-10-16

我想使用多键混合融合两个图像,但我对此功能的输入参数尚不清楚:

void detail::Blender::prepare(const std::vector<Point>& corners, const std::vector<Size>& sizes)

就我而言,我只输入了两个带有黑色差距的扭曲图像,并且带有面具全白。(原谅我不能添加图片...)

我设置了两个角(0.0,0.0),因为扭曲的图像已注册。

,但我的结果还不够好。在结果中明显接缝

有人可以告诉我为什么吗?如何解决这个问题?

我不确定当您说"我的结果还不够好"时,您是什么意思。最好观看结果,但我会尝试猜测。我的代码的主要部分是使整个全景的代码:

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的想法很明确。