我有大小为(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)
中心的距离与缩放比例成正比(在每个轴上)。
我们可以按如下方式计算newx
和newy
:
- 从
oldx
中减去x_original_center
和y_original_center
,oldy
.
减去后,(0, 0) 是"新中心"(应用"中心坐标系")。 - 按
scale_x
和scale_y
缩放"零居中"坐标。 - 通过添加
x_scaled_center
和y_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));