OpenCV doesn't provide distort function for image, but you can implement one by yourself. All you need are:
- Intrinsic params (camera matrix and distortion coefficients) and size of the distorted image.
Denoted as cam_mtx
, dis_cef
, and image_size
.
- Intrinsic params (camera matrix) and size of the undistorted image.
Denoted as cam_mtx_ud
and image_size_ud
.
- Rectification transform (rotation matrix) between distorted and undistorted images.
Denoted as R
.
The rectification transform matrix R
can be computed by stereoRectify()
, but in mono-camera system, it's normally identity (you can just use empty Mat
).
Recall the procedure when you undistort an image, it takes two steps:
- Compute the rectification maps:
initUndistortRectifyMap(cam_mtx, dis_cef, R, cam_mtx_ud, image_size_ud, CV_32FC1, map_x, map_y)
- Remap the image to undistort:
remap(image, image_ud, map_x, map_y, INTER_LINEAR);
The rectification maps (map_x
and map_y
) describe pixel-coordinate-map from the undistorted image to the distorted image. With them, every pixel on the undistorted image can find it's location on the distorted image, and then retrieve the pixel value with interpolation. That's how remap
works.
So, to produce the undistort rectification maps, you need to loop on the pixels of destination (undistorted) image and distort the points.
Now, applying distortion on an image is just similar to undistorting.
You need to produce the "distort maps" by looping on the pixels of destination (distorted) image and undistort the points. Then, use remap
to apply the distortion.
Here is the code:
Mat map_x = Mat(image_size, CV_32FC1);
Mat map_y = Mat(image_size, CV_32FC1);
vector<Point2f> pts_ud, pts_distort;
for (int y = 0; y < image_size.height; ++y)
for (int x = 0; x < image_size.width; ++x)
pts_distort.emplace_back(x, y);
undistortPoints(pts_distort, pts_ud, cam_mtx, dis_cef, R, cam_mtx_ud);
for (int y = 0; y < image_size.height; ++y) {
float* ptr1 = map_x.ptr<float>(y);
float* ptr2 = map_y.ptr<float>(y);
for (int x = 0; x < image_size.width; ++x) {
const auto& pt = pts_ud[y * image_size.width + x];
ptr1[x] = pt.x;
ptr2[x] = pt.y;
}
}
Mat image_distort;
remap(image_ud, image_distort, map_x, map_y, INTER_LINEAR);
I'm not good with python,so I wrote the code in C++. Sorry about that, but I think the code is not hard to read.