【问题标题】:How do you get the original coordinates of a point within a zoomed image?如何获得缩放图像中某个点的原始坐标?
【发布时间】:2016-01-31 10:46:33
【问题描述】:

我有一个学校作业,要求我能够使用 opencv 和 C++ 放大和缩小感兴趣的区域。感兴趣区域的大小初始化为 80*80,单击时它在垂直和水平方向上增加(左键单击)和减小(右键单击)10px。我想我已经做到了:

// callback associé à la souris sur la fenêtre "TP1"
// clic droit -> zoom arrière
// clic gauche -> zoom avant
// (x, y) indique la position de la souris sur la fenêtre
// event est un évenement de la souris (clic, souris déplacé, etc.)
// flags indique si un bouton de la souris ou du clavier est enfoncé
void cb_on_mouse(int event, int x, int y, int flags, void*)
{
    Mat tmp;    // temporary image
    bool update = false;

    // copying src to tmp
    src.copyTo(tmp);

    // copying src to dst
    src.copyTo(dst);

    // when mouse moves
    if (event == EVENT_MOUSEMOVE)
    {
        // showing x and y coordinates of the mouse on the main image
        putText(dst, "x: " + to_string(x), Point(dst.rows + 4, dst.cols - 25), CV_FONT_HERSHEY_COMPLEX, 5, (0,0,0), 8, true);
        putText(dst, "y: " + to_string(y), Point(dst.rows + 4, dst.cols - 5), CV_FONT_HERSHEY_COMPLEX, 5, (0,0,0), 8, true);
        imshow("TP1", dst);
    }

    // when a click happens
    else
    {
        // if ctrl + mouse_btn then there's no zoom
        if (flags != EVENT_FLAG_CTRLKEY + EVENT_FLAG_RBUTTON && flags != EVENT_FLAG_CTRLKEY + EVENT_FLAG_LBUTTON)
        {
            // left click zooms in
            if (event == EVENT_LBUTTONDOWN)
            {
                // zoom in limit set at 2 for both height and width
                if (roi.height > 20 && roi.width > 20)
                {
                    roi.height -= pas_yzoom;
                    roi.width -= pas_xzoom;
                }
            }

            // right click zooms out
            else if (event == EVENT_RBUTTONDOWN)
            {
                // zoom out limit is set of original image size (or close)
                if (roi.height < tmp.rows && roi.width < tmp.cols)
                {
                    roi.height += pas_yzoom;
                    roi.width += pas_xzoom;
                }
            }

            // calculating x
            // making sure it doesn't get out of bounds
            if (x - (int)(roi.width / 2) <= 0)
                roi.x = 0;

            else if (x + (int)(roi.width / 2) >= tmp.cols)
                roi.x = tmp.cols - roi.width;

            else
                roi.x = x - (int)(roi.width / 2);

            // calculating y
            // making sure it doesn't go out of bounds
            if (y - (int)(roi.height / 2) <= 0)
                roi.y = 0;

            else if (y + (int)(roi.height / 2) >= tmp.rows)
                roi.y = tmp.rows - roi.height;

            else
                roi.y = y - (int)(roi.height / 2);

            update = true;  
        }

        // only updating the image if an update took place
        if (update)
        {
            zoomed_img = tmp(roi);  // creating tmp image
            imshow("Zoom", zoomed_img); // displaying tmp
        }
    }
}

现在我需要收集有关在缩放窗口中单击的像素的信息,但我不知道如何计算其在原始图像上的坐标。我真的不知道如何处理规模和所有这些。我试过了,但它不起作用:

Mat tmp_zoom;   // temporary image for zoom
Mat tmp_src;    // temporary image for source
float base_x;   // x on original image
float base_y;   // y on original image
float scale;

zoomed_img.copyTo(tmp_zoom);
src.copyTo(tmp_src);
scale = (float)(tmp_zoom.cols * tmp_zoom.rows) / (float)(roi.width * roi.height);

if (event == EVENT_LBUTTONDOWN)
{
    base_x = ((float)x / scale);
    base_y = ((float)y / scale);

    cout << "Click on zoom: " << "\n";
    cout << "base_x: " << base_x << "\n";
    cout << "base_y: " << base_y << "\n";
    circle(tmp_src, Point(base_x, base_y), 5, (0, 0, 0), 1, 8, 0);
    imshow("TP1", tmp_src);
}

这是程序应该做的事情: image_program

希望问题描述清楚,提前感谢您的帮助。

【问题讨论】:

    标签: c++ image opencv zooming scale


    【解决方案1】:

    抱歉,我没有查看您的代码。

    如果您放大 roi,您可以记住该 roi 的放置位置(位置和大小)。

    例如:

    roi.x = 300;
    roi.y = 200;
    roi.width = 20;
    roi.height = 20;
    

    现在,如果您有一个调整大小的图像仅包含这个 20x20 区域,但调整为 100x100 像素的图像,并且您显示它,您想要单击某处并计算相应的原始位置?

    在那个放大的图片中,你知道点击坐标,比如

    click.x == 10;
    click.y == 80;
    

    现在您可以计算缩放图像内的相对图像坐标,例如

    cv::Point2f relative;
    relative.x = (float)click.x/(float)zoomedWidth;
    relative.y = (float)click.y/(float)zoomedHeight;
    

    现在在您的原始图片中,您的点击位置应该是

    cv::Point2f original;
    original.x = roi.x + relative.x*roi.width;
    original.y = roi.y + relative.y*roi.height;
    

    希望对你有帮助

    【讨论】:

    • 感谢您的回答。出于某种原因,original.x = roi.x + relative.x*roi.width; 让我获得了极高的价值(大约是应有的一千倍)。我有一个公式接近的结果是:x_scale = (double)roi.width / (double)(tmp_src.cols); y_scale = (double)roi.height / (double)(tmp_src.rows); base_x = (double)roi.x + (x * x_scale); base_y = (double)roi.y + (y * y_scale); 虽然它非常不准确。
    • 你能验证 relative.x 和 relative.y 分别在 0 和 1 之间吗? relative 应该包含缩放图像中点击的相对位置。不是比例因子!
    • 哦,我明白你的意思了。那是因为我第一次没有得到它。所以我有两个窗口,你可以在原始图片中看到。缩放后的图片与 ROI 具有相同数量的列和行。自从两天前我刚刚在学校开始图像处理以来,我对很多事情感到困惑。我会检查的
    • 好的,我已经计算了相对 x 和 y,这让我找到了解决方案。我认为这与我主要处理无法更改的整数这一事实有关。准确性还可以,但远非完美。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2022-11-19
    相关资源
    最近更新 更多