将坐标映射到调整大小的图像



我有大小为(969,348)的原始图像,调整大小的图像为(696,484)。 我在调整大小的图像中有一个点 (385,400),所以我想将其绘制到原始图像。oldx = 385 oldy = 400我已使用

resize(org, resizeimage, Size(org.rows / 0.5, org.cols / 2), 0, 0, INTER_AREA);

我正在使用OpenCV C++,如果我对行和列感到困惑,宽度和高度是多少。 我已经尝试过这个,但它给了我 (0,484) 坐标。

Point(round(float((oldx / org.cols)) * resizeimage.cols), round(float((oldy / org.rows))) * resizeimage.rows)

中心的距离与缩放比例成正比(在每个轴上)。

我们可以按如下方式计算newxnewy

  • oldx中减去x_original_centery_original_centeroldy.
    减去后,(0, 0) 是"新中心"(应用"中心坐标系")。
  • scale_xscale_y缩放"零居中"坐标。
  • 通过添加x_scaled_centery_scaled_center将"缩放零居中"坐标转换为"左上角 (0, 0)"。
<小时 />

插图:

Origin:
(0,0)                     New coordinate system: (0,0) center 
-----------------                       -----------------                
|                 | x -= (cols-1)/2     |    (0,0)        |
|                 | ===============>    |        +        |
|                 | y -= (rows-1)/2     |                 |
-----------------                       -----------------


After scaling:
The distance to the center is proportional to the scale.
In x axis the distance is proportional to x_scale
In y axis the distance is proportional to y_scale

-------------
|             |
|      ^    o |
| y*sy |      |
--------^--------                 |      |      |
|      y |     o  |    Scale       |      V      |
|        +<--->   | ===========>   |      +<-->  |
|           x     |                |       x*sx  |
-----------------                 |             |
|             |
|             |
|             |
-------------    

Convert the scaled result to origin (0, 0): 
newx += (new_cols-1)/2
newy += (new_rows-1)/2

精确计算中心:
C++换算为:
(0, 0) 为左上角坐标,(cols-1, rows-1) 为右下角坐标
精确中心坐标为:
x_original_center = (original_rows-1.0)/2.0
y_original_center = (original_cols-1.0)/2.0


C++ 代码示例:

#include <cmath>
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv2/highgui/highgui.hpp>
int main()
{
double scale_x = 2.0;
double scale_y = 0.5;
int oldx = 385;
int oldy = 400;
cv::Mat org = cv::Mat::zeros(cv::Size(969, 348), CV_8UC1);  //Fill with zeros (for example).
cv::Mat resizeimage;
//Height and width before resize:
int rows = org.rows;    //384
int cols = org.cols;    //969
//cv::resize(org, resizeimage, Size(org.rows / 0.5, org.cols / 2.0), 0, 0, INTER_AREA);
//Instead of dividing by 0.5, sacle by 2.0 (and Instead of dividing by 2.0, scale by 0.5)
cv::resize(org, resizeimage, cv::Size((int)std::round(rows * scale_x), (int)std::round(cols * scale_y)), 0, 0, cv::INTER_AREA);
//Height and width after resize:
int resized_rows = resizeimage.rows;    //485
int resized_cols = resizeimage.cols;    //696
//Center before resize:
double x_original_center = ((double)cols - 1.0) / 2.0;  //484.0
double y_original_center = ((double)rows - 1.0) / 2.0;  //173.5
//Center after resize:
double x_scaled_center = ((double)resized_cols - 1.0) / 2.0;    //347.5
double y_scaled_center = ((double)resized_rows - 1.0) / 2.0;    //242
//Subtract the center, scale, and add the "scaled center".
int newx = (int)std::round((oldx - x_original_center) * scale_x + x_scaled_center); //150
int newy = (int)std::round((oldy - y_original_center) * scale_y + y_scaled_center); //355
std::cout << "newx = " << newx << std::endl << "newy = " << newy << std::endl;
return 0;
}

我更喜欢以下方式的地图坐标:

float x_ratio = resizeimage.cols / static_cast<float>(org.cols);
float y_ratio = resizeimage.rows / static_cast<float>(org.rows);
cv::Point newPoint(static_cast<int>(oldx * x_ratio), 
static_cast<int>(oldy * y_ratio));

最新更新