Prev Tutorial: Mask operations on matrices
Next Tutorial: Adding (blending) two images using OpenCV
| |
Compatibility | OpenCV >= 3.0 |
Input/Output
Images
Load an image from a file:
C++
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
Loads an image from a file.
Java
Mat img = Imgcodecs.imread(filename);
Python
If you read a jpg file, a 3 channel image is created by default. If you need a grayscale image, use:
C++
@ IMREAD_GRAYSCALE
If set, always convert image to the single channel grayscale image (codec internal conversion).
Definition: imgcodecs.hpp:70
Java
Mat img = Imgcodecs.imread(filename, Imgcodecs.IMREAD_GRAYSCALE);
Python
img =
cv.imread(filename, cv.IMREAD_GRAYSCALE)
- Note
- Format of the file is determined by its content (first few bytes). To save an image to a file:
C++
CV_EXPORTS_W bool imwrite(const String &filename, InputArray img, const std::vector< int > ¶ms=std::vector< int >())
Saves an image to a specified file.
Java
Imgcodecs.imwrite(filename, img);
Python
- Note
- Format of the file is determined by its extension.
-
Use cv::imdecode and cv::imencode to read and write an image from/to memory rather than a file.
Basic operations with images
Accessing pixel intensity values
In order to get pixel intensity value, you have to know the type of an image and the number of channels. Here is an example for a single channel grey scale image (type 8UC1) and pixel coordinates x and y:
C++
Scalar_< double > Scalar
Definition: modules/core/include/opencv2/core/types.hpp:709
unsigned char uchar
Definition: core/include/opencv2/core/hal/interface.h:51
Java
byte[] imgData = new byte[(int) (img.total() * img.channels())];
img.get(0, 0, imgData);
byte intensity = imgData[y * img.cols() + x];
Python
C++ version only: intensity.val[0] contains a value from 0 to 255. Note the ordering of x and y. Since in OpenCV images are represented by the same structure as matrices, we use the same convention for both cases - the 0-based row index (or y-coordinate) goes first and the 0-based column index (or x-coordinate) follows it. Alternatively, you can use the following notation (C++ only):
Point2i Point
Definition: modules/core/include/opencv2/core/types.hpp:209
Now let us consider a 3 channel image with BGR color ordering (the default format returned by imread):
C++ code
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];
Vec< uchar, 3 > Vec3b
Definition: matx.hpp:441
Python Python
_blue = img[y,x,0]
_green = img[y,x,1]
_red = img[y,x,2]
You can use the same method for floating-point images (for example, you can get such an image by running Sobel on a 3 channel image) (C++ only):
float blue = intensity.
val[0];
float green = intensity.val[1];
float red = intensity.val[2];
_Tp val[m *n]
matrix elements
Definition: matx.hpp:218
Vec< float, 3 > Vec3f
Definition: matx.hpp:459
The same method can be used to change pixel intensities:
C++
img.at<
uchar>(y, x) = 128;
Java
byte[] imgData = new byte[(int) (img.total() * img.channels())];
imgData[y * img.cols() + x] = (byte) 128;
img.put(0, 0, imgData);
Python
There are functions in OpenCV, especially from calib3d module, such as cv::projectPoints, that take an array of 2D or 3D points in the form of Mat. Matrix should contain exactly one column, each row corresponds to a point, matrix type should be 32FC2 or 32FC3 correspondingly. Such a matrix can be easily constructed from std::vector
(C++ only):
vector<Point2f> points;
Mat pointsMat = Mat(points);
One can access a point in this matrix using the same method Mat::at
(C++ only):
Point_< float > Point2f
Definition: modules/core/include/opencv2/core/types.hpp:207
Memory management and reference counting
Mat is a structure that keeps matrix/image characteristics (rows and columns number, data type etc) and a pointer to data. So nothing prevents us from having several instances of Mat corresponding to the same data. A Mat keeps a reference count that tells if data has to be deallocated when a particular instance of Mat is destroyed. Here is an example of creating two matrices without copying data (C++ only):
std::vector<Point3f> points;
Mat pointsMat = Mat(points).reshape(1);
As a result, we get a 32FC1 matrix with 3 columns instead of 32FC3 matrix with 1 column. pointsMat
uses data from points and will not deallocate the memory when destroyed. In this particular instance, however, developer has to make sure that lifetime of points
is longer than of pointsMat
If we need to copy the data, this is done using, for example, cv::Mat::copyTo or cv::Mat::clone:
C++
Mat img =
imread(
"image.jpg");
Mat img1 = img.clone();
Java
Mat img = Imgcodecs.imread("image.jpg");
Mat img1 = img.clone();
Python
An empty output Mat can be supplied to each function. Each implementation calls Mat::create for a destination matrix. This method allocates data for a matrix if it is empty. If it is not empty and has the correct size and type, the method does nothing. If however, size or type are different from the input arguments, the data is deallocated (and lost) and a new data is allocated. For example:
C++
Mat img =
imread(
"image.jpg");
Mat sobelx;
#define CV_32F
Definition: core/include/opencv2/core/hal/interface.h:78
void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator.
Java
Mat img = Imgcodecs.imread("image.jpg");
Mat sobelx = new Mat();
Imgproc.Sobel(img, sobelx, CvType.CV_32F, 1, 0);
Python
_sobelx =
cv.Sobel(img, cv.CV_32F, 1, 0)
Primitive operations
There is a number of convenient operators defined on a matrix. For example, here is how we can make a black image from an existing greyscale image img
C++
Java
byte[] imgData = new byte[(int) (img.total() * img.channels())];
Arrays.fill(imgData, (byte) 0);
img.put(0, 0, imgData);
Python
Selecting a region of interest:
C++
Rect r(10, 10, 100, 100);
Mat smallImg = img(r);
Rect2i Rect
Definition: modules/core/include/opencv2/core/types.hpp:496
Java
Mat smallImg = img.submat(r);
Python
_smallImg = img[10:110,10:110]
Conversion from color to greyscale:
C++
Mat img =
imread(
"image.jpg");
Mat grey;
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0, AlgorithmHint hint=cv::ALGO_HINT_DEFAULT)
Converts an image from one color space to another.
@ COLOR_BGR2GRAY
convert between RGB/BGR and grayscale, color conversions
Definition: imgproc/include/opencv2/imgproc.hpp:555
Java
Mat img = Imgcodecs.imread("image.jpg");
Mat grey = new Mat();
Imgproc.cvtColor(img, grey, Imgproc.COLOR_BGR2GRAY);
Python
Change image type from 8UC1 to 32FC1:
C++
Java
src.convertTo(dst, CvType.CV_32F);
Python
_dst = src.astype(np.float32)
Visualizing images
It is very useful to see intermediate results of your algorithm during development process. OpenCV provides a convenient way of visualizing images. A 8U image can be shown using:
C++
Mat img =
imread(
"image.jpg");
@ WINDOW_AUTOSIZE
the user cannot resize the window, the size is constrainted by the image displayed.
Definition: highgui.hpp:144
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
int waitKey(int delay=0)
Waits for a pressed key.
void namedWindow(const String &winname, int flags=WINDOW_AUTOSIZE)
Creates a window.
Java
Mat img = Imgcodecs.imread("image.jpg");
HighGui.namedWindow("image", HighGui.WINDOW_AUTOSIZE);
HighGui.imshow("image", img);
HighGui.waitKey();
Python
A call to waitKey() starts a message passing cycle that waits for a key stroke in the "image" window. A 32F image needs to be converted to 8U type. For example:
C++
Mat img =
imread(
"image.jpg");
Mat grey;
Mat sobelx;
double minVal, maxVal;
Mat draw;
sobelx.convertTo(draw,
CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
void minMaxLoc(InputArray src, double *minVal, double *maxVal=0, Point *minLoc=0, Point *maxLoc=0, InputArray mask=noArray())
Finds the global minimum and maximum in an array.
#define CV_8U
Definition: core/include/opencv2/core/hal/interface.h:73
Java
Mat img = Imgcodecs.imread("image.jpg");
Mat grey = new Mat();
Imgproc.cvtColor(img, grey, Imgproc.COLOR_BGR2GRAY);
Mat sobelx = new Mat();
Imgproc.Sobel(grey, sobelx, CvType.CV_32F, 1, 0);
MinMaxLocResult res = Core.minMaxLoc(sobelx);
Mat draw = new Mat();
double maxVal = res.maxVal, minVal = res.minVal;
sobelx.convertTo(draw, CvType.CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));
HighGui.namedWindow("image", HighGui.WINDOW_AUTOSIZE);
HighGui.imshow("image", draw);
HighGui.waitKey();
Python
sobelx =
cv.Sobel(grey, cv.CV_32F, 1, 0)
minVal = np.amin(sobelx)
maxVal = np.amax(sobelx)
draw =
cv.convertScaleAbs(sobelx, alpha=255.0/(maxVal - minVal), beta=-minVal * 255.0/(maxVal - minVal))
void convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0)
Scales, calculates absolute values, and converts the result to 8-bit.
- Note
- Here cv::namedWindow is not necessary since it is immediately followed by cv::imshow. Nevertheless, it can be used to change the window properties or when using cv::createTrackbar