OpenCV
https://docs.opencv.org/2.4/modules/gpu/doc/gpu.html
0 = black 255 = white, max intensity
I have always been using the Python version. Time to be a man and use the C++ version.
If you want to fundamentally understand OpenCV, go through the core tutorials first:
Resources
- Video Capture https://docs.opencv.org/4.x/d8/dfe/classcv_1_1VideoCapture.html
- With CMake https://docs.opencv.org/4.x/db/df5/tutorial_linux_gcc_cmake.html
Some fundamental problems that I am running into:
- How to iterate over an image fast?
- iterate over matrix: https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a952ef1a85d70a510240cb645a90efc0d
OpenCV with GPU: https://docs.opencv.org/4.x/da/d2c/tutorial_table_of_content_gpu.html
OpenCV header files
which OpenCV header file should I include?
You can figure this info out by looking at documentation. For example,
cv::VideoCapture
documentation is here. It shows that it is included in#include <opencv2/videoio.hpp>
.
Cool Things
Some really cool things:
- OpenCV uses a reference counter, similar to the way shared_ptr is implemented. So they know when to clean up
If you want to copy the matrix, you can do this
Mat F = A.clone();
Mat G;
A.copyTo(G)
Accessing Individual Pixels
An RGB image has 3-different channels. However, usually, we only process a black and white image, because it’s much faster to process.
Cycle through pixels opencv:
This is the method in the tutorial
uchar* p;
for (int i = 0; i < img.rows; i++) {
p = img.ptr<uchar>(i);
for (int j=0;j<img.cols;j++) {
p[j] = 240;
}
}
However, there is a much faster method with multithreading
img.forEach<uchar>([](uchar &p, const int position[]) -> void {
p = 255
});
If you just need a single pixel, you can do
cout << M.at<double>(0,0);
Type conversions
This is a very common problem, because you don’t actually want to be working with uchar
everywhere throughout your codebase. That is super slow.
Mat pgm_image = imread("image.pgm", IMREAD_GRAYSCALE); //flag is important !
Mat pgm_double;
pgm_image.convertTo(pgm_double, CV_64F); // optionally scale by 1.0/255, if you need [0..1] range
double *I = pgm_double.ptr<double>(0);
https://answers.opencv.org/question/125250/converting-cvmat-to-double/
Displaying Images
https://stackoverflow.com/questions/9588719/opencv-double-mat-shows-up-as-all-white
cv::imshow works in following ways:
- If the image is 8-bit unsigned, it is displayed as is.
- If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range “[0,255*256]
is mapped to
[0,255]`. - If the image is 32-bit floating-point, the pixel values are multiplied by 255. That is, the value range
[0,1]
is mapped to[0,255]
.
Therefore, if you convert from unsigned to double, make sure to normalize if you want to display it.
For example
img = cv::imread("../livingroom.jpg", cv::IMREAD_COLOR);
cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);
img.convertTo(img, CV_64FC1, 1.0 / 255);
img.convertTo(img, CV_8UC1, 255.0);
Benchmarking
I need to benchmark opencv, to see how my implementation compares to their speed
https://docs.opencv.org/4.x/dc/d69/tutorial_dnn_superres_benchmark.html