Loại bạn gọi cv::Mat::at
có nhu cầu khớp với loại pixel riêng lẻ. Vì cv::Scalar
về cơ bản là cv::Vec<double,4>
, điều này sẽ không hoạt động đối với hình ảnh U8C3
(tất cả sẽ hoạt động với hình ảnh F64C4
).
Trong trường hợp của bạn, bạn cần một cv::Vec3b
, mà là một typedef
cho cv::Vec<uchar,3>
:
Vec3b col = I.at<Vec3b>(i, j);
Sau đó, bạn có thể chuyển đổi này vào một cv::Scalar
nếu bạn thực sự cần, nhưng kiểu của cv::Mat::at
instantiation phải phù hợp với loại hình ảnh của bạn, vì nó chỉ tạo ra dữ liệu hình ảnh mà không có bất kỳ chuyển đổi nào.
Đoạn mã thứ hai của bạn trả về một con trỏ tới hàng thứ i của hình ảnh. Nó không phải là dữ liệu không liên quan, nhưng chỉ là một con trỏ đến các giá trị uchar
đơn lẻ. Vì vậy, trong trường hợp hình ảnh U8C3
, mỗi 3 phần tử liên tiếp trong dữ liệu được trả lại thành p
phải đại diện cho một pixel. Một lần nữa, để có được tất cả các điểm ảnh như một yếu tố duy nhất sử dụng
Vec3b *p = I.ptr<Vec3b>(i);
mà lại không gì hơn là một diễn viên thích hợp của con trỏ hàng trước khi trở về nó.
EDIT: Nếu bạn muốn thực hiện nhiều lần truy cập pixel trên hình ảnh, bạn cũng có thể sử dụng loại tiện lợi cv::Mat_
. Đây là gì khác hơn là một wrapper mỏng gõ xung quanh dữ liệu hình ảnh, do đó tất cả các truy cập vào pixel hình ảnh được một cách thích hợp gõ:
Mat_<Vec3b> &U = reinterpret_cast<Mat_<Vec3b>&>(I);
Bạn có thể sau đó tự do sử dụng U(i, j)
và luôn có được một 3-tuple của chars unsigned và do đó pixel, một lần nữa mà không cần sao chép bất kỳ, chỉ cần gõ phôi (và do đó ở cùng một hiệu suất như I.at<Vec3b>(i, j)
).
Cảm ơn bạn đã phản hồi nhanh. Tôi đã thực sự bối rối với nhiều kênh và cách chúng được lưu trữ. – jnovacho