Opencv坐标系X、Y行列宽高之间的关系

row == height == Point.y
col == width  == Point.x
  • 1
  • 2

Opencv坐标系X、Y行列宽高之间的关系

这是因为在计算机中,图像是以矩阵的形式保存的。

一张宽度640像素、长度480像素的灰度图保存在一个480 * 640的矩阵中。

先行后列。

而我们习惯的坐标表示是先X横坐标,再Y纵坐标。在OpenCV中需要对矩阵进行计算,先行再列。

这种隐形的错误需要细心。

一个典型的程序示例:

#include<opencv2/opencv.hpp>

using namespace cv;

int main() {

    Mat srcImage = imread("Lenna.png");
    Mat logo = imread("smile.png");

    Mat imageROI;

    imageROI = srcImage(Rect(0, 100, logo.cols, logo.rows));
    //imageROI = srcImage(Range(0, 0 + logo.cols), Range(100, 00 + logo.rows));

    Mat mask = imread("smile.png", 0);

    logo.copyTo(imageROI, mask);

    namedWindow("LOL");
    imshow("LOL", srcImage);

    waitKey(0);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

这里

template<typename _Tp> inline
Rect_<_Tp>::Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height)
    : x(_x), y(_y), width(_width), height(_height) {}
  • 1
  • 2
  • 3

Rect的构造函数给定的X,Y坐标即为矩形的左上角坐标。
设置为(0,100),效果如下。

Opencv坐标系X、Y行列宽高之间的关系

对比例程

#include<opencv2/opencv.hpp>

using namespace cv;

int main() {

    Mat srcImage = imread("Lenna.png");
    Mat logo = imread("logo.jpg");

    Mat imageROI;

    //imageROI = srcImage(Rect(0, 200, logo.cols, logo.rows));
    imageROI = srcImage(Range(0, 0 + logo.cols), Range(200, 200 + logo.rows));

    Mat mask = imread("logo.jpg", 0);

    logo.copyTo(imageROI, mask);

    namedWindow("LOL");
    imshow("LOL", srcImage);

    waitKey(0);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

这里是直接从源图像中截取出片区域,选取的是一个从0行,200列坐标点开始的一片宽 x 高的区域。

Opencv坐标系X、Y行列宽高之间的关系

补充(详细解释)

  1. 坐标体系中的零点坐标为图片的左上角,X轴为图像矩形的上面那条水平线;Y轴为图像矩形左边的那条垂直线。该坐标体系在诸如结构体Mat,Rect,Point中都是适用的。(虽然网上有学着说OpenCV中有些数据结构的坐标原点是在图片的左下角,但是我暂时还没碰到过)。

  2. 在使用image.at(x1, x2)来访问图像中点的值的时候,x1并不是图片中对应点的x轴坐标,而是图片中对应点的y坐标。因此其访问的结果其实是访问image图像中的Point(x2, x1)点,即与image.at(Point(x2, x1))效果相同。

  3. 如果所画图像是多通道的,比如说image图像的通道数时n,则使用Mat::at(x, y)时,其x的范围依旧是0到image的height,而y的取值范围则是0到image的width乘以n,因为这个时候是有n个通道,所以每个像素需要占有n列。但是如果在同样的情况下,使用Mat::at(point)来访问的话,则这时候可以不用考虑通道的个数,因为你要赋值给获取Mat::at(point)的值时,都不是一个数字,而是一个对应的n维向量。

转载自:https://blog.****.net/oqqenvy12/article/details/71933651