【OpenCV 问题记录】(1)对于.at<uchar>(j, i) 和.at<uchar>(Point(j, i)) 的区别

本文详细解释了OpenCV库中Mat::at函数的两种使用方式:通过行列索引和坐标点获取图像像素的区别,并通过示例图帮助读者更好地理解两者的不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意!!

我在opencv实现在图像上画对角线和分割之一上说了一下自己对于Mat::at 这个类的一些看法,我觉得可能会误导了一些人,所以特意说一下这两者的区别

我说说我的理解:

srcImage.at<uchar>(j, i) //表示的是  j 行 i 列 的这个像素
srcImage.at<uchar>(Point(j, i)) //表示的是 坐标(j,i)的像素

为了我下面的图方便说明 j 换成 x , i 换成 y 。也就是说:

srcImage.at<uchar>(x, y) //表示的是 x 行 y 列 的这个像素
srcImage.at<uchar>(Point(x, y)) //表示的是 坐标(x,y)的像素

可能就会有人不明白了,有什么区别呢??
先上一幅图
坐标图
问图中红点的坐标是? (2,1) 还是 (1,2)?
答案是(2,1)!
为什么? 看清了 我问的是坐标!!
那么(2,1) 和 (1,2)究竟有什么不同?
(2,1)表示的是红点的坐标,就是红点的 x 坐标是 2, y 坐标是 1。
(1,2)表示的是红点的行和列,就是红点的行是1,列是2,也就是红点在第 1 行,第 2 列。
这下子我相信大家都明白这两者的区别了吧

srcImage.at<uchar>(j, i)
srcImage.at<uchar>(Point(j, i))
*v = false; Mat matEdge; Mat src = srcMat.clone(); threshold(src, matEdge, 0, 255, THRESH_OTSU); Canny(matEdge, matEdge, 3, 9, 3); Mat pointList = Mat(1, 2, CV_32FC1, Scalar(0)); Mat List1 = Mat(1, 2, CV_32FC1, Scalar(0)); Mat List2 = Mat(1, 2, CV_32FC1, Scalar(0)); Mat point = Mat(1, 2, CV_32FC1, Scalar(0)); float cu = 0, cv = 0; int row = matEdge.rows, col = matEdge.cols; for (int v = 0; v < row; v++) { for (int u = 0; u < col; u++) { if (matEdge.ptr<uchar>(v)[u] > 0) { point.ptr<float>(0)[0] = u; point.ptr<float>(0)[1] = v; pointList.push_back(point); cu = cu + u; cv = cv + v; } } } if (pointList.rows < 3) return; pointList = pointList(Range(1, pointList.rows), Range(0, 2)); cu = cu / pointList.rows; cv = cv / pointList.rows; float a1, b1, a2, b2, dt; a1 = 1, b1 = 0, a2 = 0, b2 = 1; dt = 0.20*matEdge.rows; float tempu, tempv, d, tempa, tempb, tempR1, tempR2; row = pointList.rows; for (int i = 0; i < row; i++) { tempu = pointList.ptr<float>(i)[0] - cu; tempv = pointList.ptr<float>(i)[1] - cv; pointList.ptr<float>(i)[0] = tempu; pointList.ptr<float>(i)[1] = tempv; d = sqrt(tempu*tempu + tempv*tempv); if (d < dt) continue; //忽略离中心太近的点 tempa = tempu / d; tempb = tempv / d; tempR1 = abs(a1*tempa + b1*tempb); tempR2 = abs(a2*tempa + b2*tempb); if (tempR1 > tempR2) { if ((a1*tempa + b1*tempb) > 0) { a1 = (a1 + tempa) / 2; b1 = (b1 + tempb) / 2; } else { a1 = (a1 - tempa) / 2; b1 = (b1 - tempb) / 2; } point.ptr<float>(0)[0] = tempu; point.ptr<float>(0)[1] = tempv; List1.push_back(point); } else { if ((a2*tempa + b2*tempb) > 0) { a2 = (a2 + tempa) / 2; b2 = (b2 + tempb) / 2; } else { a2 = (a2 - tempa) / 2; b2 = (b2 - tempb) / 2; } point.ptr<float>(0)[0] = tempu; point.ptr<float>(0)[1] = tempv; List2.push_back(point); } } //修正直线向量 List1 = List1(Range(1, List1.rows), Range(0, 2)); List2 = List2(Range(1, List2.rows), Range(0, 2)); if (List1.rows < 3 || List2.rows < 3) return; Mat U1, W1, V1, U2, W2, V2; SVD::compute(List1, W1, U1, V1); SVD::compute(List2, W2, U2, V2); a1 = V1.ptr<float>(0)[0]; b1 = V1.ptr<float>(0)[1]; a2 = V2.ptr<float>(0)[0]; b2 = V2.ptr<float>(0)[1]; Mat mR = (Mat_<float>(1, 4) << a1, b1, a2, b2); //检查点数量 float numT = 0; if (abs(a1) > abs(b1)) numT = 2 * matEdge.rows / abs(a1); else numT = 2 * matEdge.rows / abs(b1); if (pointList.rows < 0.8 * numT || pointList.rows > 2 * numT) return; //记录与正交直线的近似性 float record = 0, temp1, temp2; row = pointList.rows; for (int i = 0; i < row; i++) { temp1 = abs(pointList.ptr<float>(i)[0] * a1 + pointList.ptr<float>(i)[1] * b1); temp2 = abs(pointList.ptr<float>(i)[0] * a2 + pointList.ptr<float>(i)[1] * b2); if (temp1 > temp2) temp1 = temp2; if (temp1 > dt) record++; } if (record == 0) { *lineVec = mR.clone(); *v = true; } 怎么提高垂直度的判断
最新发布
08-01
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值