-
Notifications
You must be signed in to change notification settings - Fork 31
OpenCV Tutorials
The OpenCV cv::Mat
is not a completely generic data structure. There are some limitations on the types of elements that can be stored in a cv::Mat
. Specifically, the element type must be a Plain Old Data (POD) type. For single channel images, the element type will generally be a primitive type such as unsigned char
or float
. For multi channel images, the element type will generally be cv::Vec<a primitive type, NUM_CHANNELS>
which is effectively just a convenience wrapper around an array.
OpenCV provides a type traits class for element types. This class DataType
provides a way to get type information such as the working type associated with an element type. One of its most useful abilities is to convert a static element type into the integral type identifier that the cv::Mat
retains in order to keep track of its type.
// these are the most common representation types for gray and color images
cv::DataType<unsigned char>::type == grayImage.type();
cv::DataType<cv::Vec<unsigned char, 3> >::type == colorImage.type()
The integral type of an element type can also be specified by predefined macros. This is the C way of doing things. The names of the macros are systematically formed from four components.
- signed vs unsigned
- integral vs floating point
- bit depth
- number of channels
// There are macros defined for the most common types. The macro names have a standard format
// CV_<bit-depth>{U|S|F}C(<number_of_channels>)
// Examples:
CV_8UC1 // single channel 8-bit unsigned integral pixel type.
CV_16SC2 // two channel 16-bit signed integral pixel type.
CV_32FC3 // three channel 32-bit floating point pixel type.
CV_64FC(N) // N channel 64-bit floating point pixel type.
// Shorthand -- assumes single channel
CV_8U == cv::DataType<unsigned char>::type
int rows = 640;
int cols = 480;
cv::Mat garyImg(rows, cols, cv::DataType<unsigned char>::type);
cv::Mat colorImg(rows, cols, CV_8UC3);
// cv::Mat acts as though it has reference semantics
// it is effectively a shared smart pointer to the underlying data
cv::Mat referenceToColorImg = cv::Mat(colorImg);
// reference to a subregion (no data is copied)
int regionWidth = 10;
int regionHeight = 10;
int upperLeftX = 0;
int upperLeftY = 0;
cv::Rect rect(upperLeftX, upperLeftY, regionWidth, regionHeight);
cv::Mat region = cv::Mat(referenceToColorImage, rect);
cv::Mat img = cv::imread("image.png");
assert(img.channels() == 1);
assert(img.type() == cv::DataType<unsigned char>::type)
for(int row = 0; row < img.rows; row++)
{
// get a pointer to the first pixel in the current row
unsigned char* rowPtr = img.ptr<unsigned char>(row);
for(int col = 0; col < ch1.cols; col++)
{
unsigned char value_at_row_col = rowPtr[col];
}
}
cv::Mat img = cv::imread("image.png");
assert(img.type() == cv::DataType<unsigned char>::type)
for(int row = 0; row < image.rows; row++)
{
// get a pointer to the first pixel in the current row
unsigned char* rowPtr = image.ptr<unsigned char>(row);
for(int col = 0; col < image.cols; col++)
{
for(int ch = 0; ch < image.channels(); ch++)
{
unsigned char value_at_row_col = rowPtr[col * image.channels() + ch];
}
}
}