OpenCV Point(x,y)表示(列,行)或(行,列)

use*_*190 54 opencv

我在Matrix src中有300*200的图像.我正在对图像进行以下操作.

for(int i=0;i<src.rows;i++){
for(int j=0;j<src.cols;j++){
line( src, Point(i,j),Point(i,j), Scalar( 255, 0, 0 ),  1,8 );
}
]
imshow("A",src);
waitKey(0);
Run Code Online (Sandbox Code Playgroud)

我期待它以白色覆盖整个图像,但图像的下半部分仍然是空的.如果我这样做的话

  for(int i=0;i<src.rows;i++){
    for(int j=0;j<src.cols;j++){
    src.at<uchar>(i,j)=255;
    }
    ]
    imshow("A",src);
    waitKey(0);
Run Code Online (Sandbox Code Playgroud)

整个图像覆盖白色.所以,这意味着src.at(i,j)使用(i,j)作为(行,列),但Point(x,y)使用(x,y)作为(列,行)

Mic*_*cka 88

所以,这意味着src.at(i,j)使用(i,j)作为(行,列),但Point(x,y)使用(x,y)作为(列,行)

那是对的!由于这似乎让很多人感到困惑,我会写下我的解释,原因如下:

在OpenCV中,cv::Mat用于图像和矩阵,因为离散图像基本上与矩阵相同.

在数学中,我们有一些不同的东西:

  1. 矩阵,具有多个行和多个列.
  2. (函数的)图形,具有多个轴并以图形的形式图形表示图形.
  3. 点,由坐标系的轴排序,通常是笛卡尔坐标.

1.对于矩阵的数学表示法是以行优先次序是订购

按照传统的矩阵表示法,行由二维数组的第一个索引编号,列由第二个索引编号,即a1,2是第一行的第二个元素,向下和向右计数.(注意这与笛卡尔惯例相反.)

摘自http://en.wikipedia.org/wiki/Row-major_order#Explanation_and_example

与数学一样,row:0,column:0是矩阵的左上角元素.行/列就像表格一样......

0/0---column--->
 |
 |
row
 |
 |
 v
Run Code Online (Sandbox Code Playgroud)

2.对于Points,选择一个坐标系来完成两件事:1.它使用与矩阵表示法相同的单位大小和相同的"原点",因此左上角是Point(0,0),轴长度1表示1行或1列的长度.2.它使用"图像符号"进行轴排序,这意味着横坐标(横轴)是指定x方向的第一个值,纵坐标(纵轴)是指定y方向的第二个值.

轴相交的点是两条数字线的共同原点,简称为原点.它通常标记为O,如果是,那么轴称为Ox和Oy.定义了x轴和y轴的平面通常称为笛卡尔平面或xy平面.x的值称为x坐标或横坐标,y的值称为y坐标或纵坐标.

字母的选择来自原始约定,即使用字母表的后半部分来表示未知值.字母表的第一部分用于指定已知值.

http://en.wikipedia.org/wiki/Cartesian_coordinate_system#Two_dimensions

所以在一个完美的世界里,我们会选择点/图像的坐标系:

 ^
 |
 |
 Y
 |
 |
0/0---X--->
Run Code Online (Sandbox Code Playgroud)

但由于我们希望将左上角和正值的原点转到底部,而是:

0/0---X--->
 |
 |
 Y
 |
 |
 v
Run Code Online (Sandbox Code Playgroud)

因此对于图像处理,人行首先表示法可能很奇怪,但对于数学家来说,x轴 - 首先访问矩阵会很奇怪.

所以在OpenCV中,你可以使用:mat.at<type>(row,column)或者mat.at<type>(cv::Point(x,y))访问如果相同点x=columny=row这是完全可以理解=)

希望这是正确的.我对这些符号知之甚少,但这就是我在数学和成像方面的经验告诉我的.

  • 有趣的事实:在学校我无法轻易记住一开始的矩阵索引排序,所以我有根据的猜测是“列索引可能在前,因为它与 x 轴方向相同,点在前”.. . 不幸的是错了:-( (2认同)

Tom*_*oto 8

这是一个区分 python 的 [row, columns] 和 OpenCV 的 [x,y] 的直观示例。

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = np.zeros((5,5))  # initialize empty image as numpy array
img[0,2] = 1  # assign 1 to the pixel of row 0 and column 2

M = cv2.moments(img)  # calculate moments of binary image
cX = int(M["m10"] / M["m00"])  # calculate x coordinate of centroid
cY = int(M["m01"] / M["m00"])  # calculate y coordinate of centroid

img2 = np.zeros((5,5))  # initialize another empty image
img2[cX,cY] = 1  # assign 1 to the pixel with x = cX and y = cY

img3 = np.zeros((5,5))  # initialize another empty image
img3[cY,cX] = 1  # invert x and y

plt.figure()
plt.subplots_adjust(wspace=0.4)  # add space between subplots
plt.subplot(131), plt.imshow(img, cmap = "gray"), plt.title("With [rows,cols]")
plt.subplot(132), plt.imshow(img2, cmap = "gray"), plt.title("With [x,y]")
plt.subplot(133), plt.imshow(img3, cmap= "gray"), plt.title("With [y,x]"), plt.xlabel('x'), plt.ylabel('y')
Run Code Online (Sandbox Code Playgroud)

这将输出:

在此输入图像描述


Dev*_*wal 6

I found a quick and fast fix to this problem by just converting the coordinates from opencv to Cartesian coordinates in 4th quadrant, simply by putting a (-)ve sign in front of the y coordinate.

通过这种方式,我能够在 opencv 中使用我现有的算法和所有标准笛卡尔系统方程,而不会通过在坐标系之间进行昂贵的转换而给系统带来太多开销。

0/0---X--->
 |
 |
 Y
 |
 |
 v
 (opencv)

0/0---X----> 
|
|
|
-Y
|
|
v
(4th quadrant)
Run Code Online (Sandbox Code Playgroud)