【问题标题】:Image Shearing C++图像剪切 C++
【发布时间】:2018-04-10 11:12:52
【问题描述】:

我正在尝试使用 OpenCV 加载图像沿 X 轴剪切图像,并使用以下算法剪切图像:x′=x+y·Bx,但由于某种原因,我最终得到以下剪切:

我的源代码如下所示:

#include "stdafx.h"
#include "opencv2\opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
    Mat src = imread("B2DBy.jpg", 1);

    if (src.empty())
        cout << "Error: Loading image" << endl;

    int r1, c1; // tranformed point
    int rows, cols; // original image rows and columns
    rows = src.rows;
    cols = src.cols;

    float Bx = 2; // amount of shearing in x-axis
    float By = 0; // amount of shearing in y-axis

    int maxXOffset = abs(cols * Bx);
    int maxYOffset = abs(rows * By);

    Mat out = Mat::ones(src.rows + maxYOffset, src.cols + maxXOffset, src.type()); // create output image to be the same as the source

    for (int r = 0; r < out.rows; r++) // loop through the image
    {
        for (int c = 0; c < out.cols; c++)
        {
            r1 = r + c * By - maxYOffset; // map old point to new
            c1 = r * Bx + c - maxXOffset;

            if (r1 >= 0 && r1 <= out.rows && c1 >= 0 && c1 <= out.cols) // check if the point is within the boundaries
            {
                out.at<uchar>(r, c) = src.at<uchar>(r1, c1); // set value
            }

        }
    }

    namedWindow("Source image", CV_WINDOW_AUTOSIZE);
    namedWindow("Rotated image", CV_WINDOW_AUTOSIZE);
    imshow("Source image", src);
    imshow("Rotated image", out);

    waitKey(0);

    return 0;
}

编辑

自己修好了。 不需要减去偏移量。这是更新的源代码:

Mat forward(Mat img) {

Mat umg = img;
int y1, x1; // tranformed point
int rows, cols; // original image rows and columns
rows = umg.rows;
cols = umg.cols;

float Bx = 0.7; // amount of shearing in x-axis
float By = 0; // amount of shearing in y-axis

int maxXOffset = abs(rows * Bx);
int maxYOffset = abs(cols * By);

Mat out = Mat::ones(rows + maxYOffset, cols + maxXOffset, umg.type()); // create output image to be the same as the source

for (int y = 0; y < rows; y++) // loop through the image
{
    for (int x = 0; x < cols; x++)
    {
        y1 = y + x * By; // map old point to new
        x1 = y * Bx + x;

        out.at<uchar>(y1, x1) = umg.at<uchar>(y, x); // set value
    }
}

return out;
}

Mat backwards(Mat img) {

Mat umg = img;
int y1, x1; // tranformed point
int rows, cols; // original image rows and columns
rows = umg.rows;
cols = umg.cols;

float Bx = 0.7; // amount of shearing in x-axis
float By = 0; // amount of shearing in y-axis

int maxXOffset = abs(rows * Bx);
int maxYOffset = abs(cols * By);

Mat out = Mat::ones(rows + maxYOffset, cols + maxXOffset, umg.type()); // create output image to be the same as the source

for (int y = 0; y < rows; y++) // loop through the image
{
    for (int x = 0; x < cols; x++)
    {
        //y1 = y + x * By; // map old point to new
        //x1 = y * Bx + x;

        y1 = (1 / (1 - Bx*By)) * (y + x * By);
        x1 = (1 / (1 - Bx*By)) * (y * Bx + x);

        out.at<uchar>(y1, x1) = umg.at<uchar>(y, x); // set value
    }
}

return out;
}

int main()
{
Mat src = imread("B2DBy.jpg", 0);

if (src.empty())
    cout << "Error: Loading image" << endl;

Mat forwards = forward(src);
Mat back = backwards(src);

namedWindow("Source image", CV_WINDOW_NORMAL);
imshow("Source image", src);
imshow("back", back);
imshow("forward image", forwards);

waitKey(0);

return 0;
}

【问题讨论】:

  • 你的结果有什么问题?
  • 我没有得到完整的图像。它以一种奇怪的方式剪切了图像!
  • in.Mat src = imread("B2DBy.jpg", 1); 1 是“灰度”的代码吗?剪切是如何定义的?为什么不使用单应性翘曲来计算剪切?
  • 您能否通过在最里面的 if 子句中添加对 r1-r 的测试来找出应用于图像的最大实际偏移量?
  • 我会在第一步中通过计算偏移量而不是绝对位置来实现它。我发现很难获得您的剪切算法,并且我认为 r1 和 c1 计算以及最大偏移量计算中也存在错误。

标签: c++ opencv image-processing


【解决方案1】:

我找到了一些时间来解决这个问题。 现在我明白了你试图通过偏移计算来实现什么,但我不确定你的是否正确。

如果需要,只需将所有 cv::Vec3b 更改为 unsigned charuchar 并加载为灰度。

请试试这个代码,也许你会发现你的错误:

// no interpolation yet
// cv::Vec3b only
cv::Mat shear(const cv::Mat & input, float Bx, float By)
{
    if (Bx*By == 1)
    {
        throw("Shearing: Bx*By==1 is forbidden");
    }


    if (input.type() != CV_8UC3) return cv::Mat();

    // shearing:
    // x'=x+y·Bx
    // y'=y+x*By

    // shear the extreme positions to find out new image size:
    std::vector<cv::Point2f> extremePoints;
    extremePoints.push_back(cv::Point2f(0, 0));
    extremePoints.push_back(cv::Point2f(input.cols, 0));
    extremePoints.push_back(cv::Point2f(input.cols, input.rows));
    extremePoints.push_back(cv::Point2f(0, input.rows));

    for (unsigned int i = 0; i < extremePoints.size(); ++i)
    {
        cv::Point2f & pt = extremePoints[i];
        pt = cv::Point2f(pt.x + pt.y*Bx, pt.y + pt.x*By);
    }

    cv::Rect offsets = cv::boundingRect(extremePoints);

    cv::Point2f offset = -offsets.tl();
    cv::Size resultSize = offsets.size();

    cv::Mat shearedImage = cv::Mat::zeros(resultSize, input.type()); // every pixel here is implicitely shifted by "offset"

    // perform the shearing by back-transformation
    for (int j = 0; j < shearedImage.rows; ++j)
    {

        for (int i = 0; i < shearedImage.cols; ++i)
        {
            cv::Point2f pp(i, j);

            pp = pp - offset; // go back to original coordinate system

            // go back to original pixel:
            // x'=x+y·Bx
            // y'=y+x*By
            //   y = y'-x*By
            //     x = x' -(y'-x*By)*Bx 
            //     x = +x*By*Bx - y'*Bx +x'
            //     x*(1-By*Bx) = -y'*Bx +x'
            //     x = (-y'*Bx +x')/(1-By*Bx)

            cv::Point2f p;
            p.x = (-pp.y*Bx + pp.x) / (1 - By*Bx);
            p.y = pp.y - p.x*By;

            if ((p.x >= 0 && p.x < input.cols) && (p.y >= 0 && p.y < input.rows))
            {
                // TODO: interpolate, if wanted (p is floating point precision and can be placed between two pixels)!
                shearedImage.at<cv::Vec3b>(j, i) = input.at<cv::Vec3b>(p);
            }
        }
    }

    return shearedImage;
}


int main(int argc, char* argv[])
{
    cv::Mat input = cv::imread("C:/StackOverflow/Input/Lenna.png");

    cv::Mat output = shear(input, 0.7, 0);
    //cv::Mat output = shear(input, -0.7, 0);
    //cv::Mat output = shear(input, 0, 0.7);

    cv::imshow("input", input);
    cv::imshow("output", output);

    cv::waitKey(0);
    return 0;
}

为我提供 3 个示例行的这些输出:

【讨论】:

    猜你喜欢
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2013-06-19
    • 2013-09-30
    • 2014-12-09
    • 2015-07-07
    • 2019-08-06
    相关资源
    最近更新 更多