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

时间:2014-09-03 10:55:51

标签: 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);

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

  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);

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

4 个答案:

答案 0 :(得分:80)

  

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

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

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

在数学方面,我们有不同的东西:

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

  4. 1。对于矩阵,数学表示法是按行主顺序排序,

      

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

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

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

    0/0---column--->
     |
     |
    row
     |
     |
     v
    

    2. 对于,选择的坐标系统可以完成两件事: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--->
    

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

    0/0---X--->
     |
     |
     Y
     |
     |
     v
    

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

    因此,在OpenCV中,您可以使用:mat.at<type>(row,column)mat.at<type>(cv::Point(x,y))来访问同一点x=columny=row,这是完全可理解的=)

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

答案 1 :(得分:2)

我通过在第四象限中将坐标从opencv转换为笛卡尔坐标,只需在y坐标前面放置一个( - )ve符号即可快速快速地解决这个问题。

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

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

0/0---X----> 
|
|
|
-Y
|
|
v
(4th quadrant)

答案 2 :(得分:0)

这是一个直观的示例,可将python的[行,列]与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  # inver x and y

plt.figure()
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]")

这将输出:

enter image description here

答案 3 :(得分:0)

按照惯例,指向 OpenCV 后跟 (x, y)。在计算机屏幕上,x 是按列排列的,而 y 是按行排列的。这是使用内置 circle 函数的示例。

win_name = "Test"
    
image_width, image_height = 300, 200
center_x, center_y = 300, 0
   
circle_radius = 9 
    
# Create a black image
img = np.zeros((image_height, image_width, 3), np.uint8)
# BGR
cv2.circle(img, center=tuple([center_x, center_y]), 
    radius=circle_radius, color=(255,0,0), 
    thickness=-1)
        
# Open openCV window
cv2.namedWindow(win_name, cv2.WINDOW_NORMAL)
cv2.resizeWindow(win_name, image_width, image_height)
cv2.moveWindow(win_name, 120, 850)
cv2.setWindowTitle(win_name, win_name)
cv2.imshow(win_name, img) 
k = cv2.waitKey(0)

顺便说一下,它们在制作图像时遵循高度和宽度顺序,并且 BGR 颜色格式不是 RGB。这与传统相反。