How would I be able to cycle through an image using opencv as if it were a 2d array to get the rgb values of each pixel? Also, would a mat be preferable over an iplimage for this operation?
putImageData(imgData, 0, 0); The image will then change according to the changes you made to its pixel array. Each pixel contains 4 components red, green, blue, alpha - each of them is number 0-255. The loop starts from top-left to bottom-right.
If efficiency is important, a fast way to iterate over pixels in a cv::Mat object is to use its ptr<T>(int r) method to obtain a pointer to the beginning of row r (0-based index). According to the matrix type, the pointer will have a different template. For CV_8UC1 : uchar* ptr = image. ptr<uchar>(r);
You can simply use affine transformation translation matrix (which is for shifting points basically). cv::warpAffine() with proper transformation matrix will do the trick. where: tx is shift in the image x axis, ty is shift in the image y axis, Every single pixel in the image will be shifted like that.
Figure 5: In OpenCV, pixels are accessed by their (x, y)-coordinates. The origin, (0, 0), is located at the top-left of the image. OpenCV images are zero-indexed, where the x-values go left-to-right (column number) and y-values go top-to-bottom (row number). Here, we have the letter “I” on a piece of graph paper.
cv::Mat
is preferred over IplImage
because it simplifies your code
cv::Mat img = cv::imread("lenna.png"); for(int i=0; i<img.rows; i++) for(int j=0; j<img.cols; j++) // You can now access the pixel value with cv::Vec3b std::cout << img.at<cv::Vec3b>(i,j)[0] << " " << img.at<cv::Vec3b>(i,j)[1] << " " << img.at<cv::Vec3b>(i,j)[2] << std::endl;
This assumes that you need to use the RGB values together. If you don't, you can uses cv::split to get each channel separately. See etarion's answer for the link with example.
Also, in my cases, you simply need the image in gray-scale. Then, you can load the image in grayscale and access it as an array of uchar.
cv::Mat img = cv::imread("lenna.png",0); for(int i=0; i<img.rows; i++) for(int j=0; j<img.cols; j++) std::cout << img.at<uchar>(i,j) << std::endl;
UPDATE: Using split to get the 3 channels
cv::Mat img = cv::imread("lenna.png"); std::vector<cv::Mat> three_channels = cv::split(img); // Now I can access each channel separately for(int i=0; i<img.rows; i++) for(int j=0; j<img.cols; j++) std::cout << three_channels[0].at<uchar>(i,j) << " " << three_channels[1].at<uchar>(i,j) << " " << three_channels[2].at<uchar>(i,j) << std::endl; // Similarly for the other two channels
UPDATE: Thanks to entarion for spotting the error I introduced when copying and pasting from the cv::Vec3b example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With