【问题标题】:OpenCv: Translate Image, Wrap Pixels Around Edges (C++)OpenCv:翻译图像,将像素环绕在边缘 (C++)
【发布时间】:2020-01-26 04:34:55
【问题描述】:

我正在尝试将图像水平平移 x 像素,垂直平移 y 像素,所以 .但是,我希望像素环绕边缘。基本上...

我们从图片一开始...

移动 x 个像素...

并移动 y 个像素...

据我所知,OpenCv 的 warpAffine() 无法做到这一点。通常,我只会循环遍历图像并将像素移动一定量,但这样做我只能水平移动它们。解决此问题的最有效方法是什么?

【问题讨论】:

    标签: c++ algorithm opencv image-processing


    【解决方案1】:

    您可以使用np.roll()

    这是一个可视化

    我在 Python 中实现了它,但您可以在 C++ 中应用类似的滚动技术

    import cv2
    import numpy as np
    
    image = cv2.imread('1.jpg')
    
    shift_x = 800
    shift_y = 650
    
    # Shift by x-axis
    for i in range(image.shape[1] -1, shift_x, -1):
        image = np.roll(image, -1, axis=1)
        image[:, -1] = image[:, 0]
        cv2.imshow('image', image)
        cv2.waitKey(1)
    
    # Shift by y-axis
    for i in range(image.shape[1] -1, shift_y, -1):
        image = np.roll(image, -1, axis=0)
        image[:, -1] = image[:, 0]
        cv2.imshow('image', image)
        cv2.waitKey(1)
    
    cv2.imshow('image', image)
    cv2.waitKey()
    

    【讨论】:

    • 很好的解决方案,但仅限于 Python,而不是作为 OP 标记的 C++。
    【解决方案2】:

    在我看来,最“有效”的方法是使用cv::Rect设置四个对应的ROI,并使用cv::copyTo手动复制内容。或许,也有可能不复制实际内容,只指向输入cv::Mat中的数据——但不幸的是,至少我找不到。

    不过,这是我的代码:

    // Shift input image by sx pixels to the left, and sy pixels to the top.
    cv::Mat transWrap(cv::Mat& input, const int sx, const int sy)
    {
        // Get image dimensions.
        const int w = input.size().width;
        const int h = input.size().height;
    
        // Initialize output with same dimensions and type.
        cv::Mat output = cv::Mat(h, w, input.type());
    
        // Copy proper contents manually.
        input(cv::Rect(sx, sy, w - sx, h - sy)).copyTo(output(cv::Rect(0, 0, w - sx, h - sy)));
        input(cv::Rect(0, sy, sx, h - sy)).copyTo(output(cv::Rect(w - sx, 0, sx, h - sy)));
        input(cv::Rect(sx, 0, w - sx, sy)).copyTo(output(cv::Rect(0, h - sy, w - sx, sy)));
        input(cv::Rect(0, 0, sx, sy)).copyTo(output(cv::Rect(w - sx, h - sy, sx, sy)));
    
        return output;
    }
    
    int main()
    {
        cv::Mat input = cv::imread("images/tcLUa.jpg", cv::IMREAD_COLOR);
        cv::resize(input, input, cv::Size(), 0.25, 0.25);
        cv::Mat output = transWrap(input, 300, 150);
    
        return 0;
    }
    

    当然,代码看起来是重复的,但被包装成一个自己的函数,它不会在你的主代码中打扰你。 ;-)

    输出应该是你想要达到的目标:

    希望有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-18
      • 1970-01-01
      • 2018-10-24
      • 1970-01-01
      • 2011-01-14
      • 1970-01-01
      • 2013-09-29
      相关资源
      最近更新 更多