Typ, który wywołujesz cv::Mat::at
z potrzebą dopasowania do typu poszczególnych pikseli. Ponieważ cv::Scalar
jest w zasadzie wartością cv::Vec<double,4>
, nie będzie to działać dla obrazu U8C3
(będzie to oczywiście działać dla obrazu F64C4
).
W twoim przypadku trzeba cv::Vec3b
, który jest typedef
dla cv::Vec<uchar,3>
:
Vec3b col = I.at<Vec3b>(i, j);
Następnie można przekonwertować to do cv::Scalar
jeśli naprawdę musisz, ale typ cv::Mat::at
instancji musi odpowiadać rodzaj obrazu, ponieważ po prostu przesyła dane obrazu bez żadnych konwersji.
Twój drugi fragment kodu zwraca wskaźnik do owego wiersza obrazu. Nie ma żadnych niepowiązanych danych, ale tylko wskaźnik do pojedynczych wartości uchar
. Tak więc w przypadku obrazu U8C3
każde kolejne 3 elementy danych zwróconych do p
powinny reprezentować jeden piksel. Ponownie, aby każdy piksel jako pojedynczy element używać
Vec3b *p = I.ptr<Vec3b>(i);
co znowu nie robi nic więcej niż odpowiedniej obsady wskaźnik rzędzie przed wpuszczeniem go.
EDYCJA: Jeśli chcesz uzyskać dostęp do wielu pikseli na obrazie, możesz również skorzystać z wygodnego typu cv::Mat_
. To nic więcej niż wpisany cienką owinięcia wokół danych obrazu, dzięki czemu wszystkie dostępy do pikseli obrazu są odpowiednio wpisane:
Mat_<Vec3b> &U = reinterpret_cast<Mat_<Vec3b>&>(I);
Można wtedy swobodnie korzystać U(i, j)
i zawsze dostać 3-krotki niepodpisanych znaków i dlatego piksele, znowu bez żadnego kopiowania, wystarczy wpisać odlewy (a zatem z taką samą wydajnością jak I.at<Vec3b>(i, j)
).
Dzięki za szybką odpowiedź. Byłem bardzo zdezorientowany wieloma kanałami i jak są przechowywane. – jnovacho