Geometric Transformation
Geometric transformation can be seen as a change in the space position of an object (or pixel) in an image, or the movement of pixels.
Geometric operations require two steps: spatial transformation and gray-level difference. pixels map to new coordinate positions by transformation. The new positions may be between several pixels, that is, not necessarily integer coordinates. In this case, the gray-level difference value is required to match the new coordinate of the ing to the output pixel. The simplest method of interpolation is the nearest neighbor interpolation, which means that the gray value of the output pixel is equal to the pixel mapped to the nearest position. This method may produce sawtooth. This method is also called zero-order interpolation, and there are also complex first-order and higher-order interpolation.
The interpolation algorithm can be understood as long as it is understood. What needs to be understood in image processing is space transformation.
Spatial transformation
The space transform corresponds to the matrix's affine transformation. A new coordinate position of a coordinate transformed by a function:
So in the program, we can use a 2*3 array structure to store the transformation matrix:
Taking the simplest translation transformation as an example, the coordinate of translation (b1, b2) can be expressed:
Therefore, the transformation matrix and inverse matrix of the translation transformation are recorded:
Zoom-in and zoom-out: the x-axis and Y-axis of the image are amplified (or reduced) by SX times, and the transformation matrix and inverse matrix are:
Select transform: rotate angle a counterclockwise around the origin. The transformation matrix and inverse matrix (clockwise selected) are as follows:
Image Transformation functions in opencv
Basic radiology transformation functions:
Void cvwarpaffine (const cvarr * SRC, // input image cvarr * DST, // output image const cvmat * map_matrix, // 2*3 Transformation Matrix int flags = cv_inter_linear + cv_warp_fill_outliers, // a combination of interpolation methods cvscalar fillval = cvscalarall (0) // used to fill values outside the boundary );
Another similar function is cvgetquadranglesubpix:
Void cvgetquadranglesubpix (const cvarr * SRC, // input image cvarr * DST, // The transformed matrix of the extracted quadrilateral const cvmat * map_matrix/2*3 );
This function is used to extract the Quadrilateral from the input image and store it in DST through map_matrix transformation. It has the same meaning as warpaffine transformation,
That is, the transformation of each vertex:
The difference between warpaffine and getquadranglesubpix is that cvwarpaffine requires that the input and output images have the same data type and have higher resource overhead (so it is not suitable for small images), and the output images can be retained. Cvgetquadranglesubpix can accurately extract a quadrilateral from an 8-bit image to a floating-point cache, which has a low system overhead and always changes the content of the output image.
Practice: Image Rotation Transformation (original size) first uses cvwarpaffine to rotate the degree angle counterclockwise.
// Rotate the image degree angle (original size) void rotateimage (iplimage * IMG, iplimage * img_rotate, int degree) counterclockwise {// rotate the center to the image center cvpoint2d32f center; center. X = float (IMG-> width/2.0 + 0.5); Center. y = float (IMG-> height/2.0 + 0.5); // calculate the two-dimensional rotating affine transform matrix float M [6]; cvmat M = cvmat (2, 3, cv_32f, m); cv2drotationmatrix (center, degree, 1, & M); // convert the image and fill the remaining values with black cvwarpaffine (IMG, img_rotate, & M, cv_inter_linear + cv_warp_fill_outliers, cvscalarall (0 ));}
Result of rotating the value of 30 degrees counterclockwise:
Here we retain the original image size for the new image. This effect is obviously not very good. We can calculate the size of the enlarged image accordingly. Practice: to rotate and transform an image (Retain the original image content and enlarge the size), the size of the new image needs to be calculated as follows: Therefore, the size of the new image is (width * Cos (A) + height * sin (), height * Cos (A) + width * sin ())
// The size of the rotated image remains unchanged, and the size of the image increases accordingly. iplimage * rotateimage1 (iplimage * IMG, int degree) {double angle = degree * cv_pi/180 .; // radian double A = sin (angle), B = cos (angle); int width = IMG-> width; int Height = IMG-> height; int width_rotate = int (height * FABS (A) + width * FABS (B); int height_rotate = int (width * FABS (A) + height * FABS (B )); // rotate the array map // [M0 M 1 m2] ==> [A11 A12 B1] // [m3 M4 M5] ==> [A21 A22 B2] float Map [6]; cvmat map_matrix = cvmat (2, 3, cv_32f, MAP); // rotation center cvpoint2d32f center = cvpoint2d32f (width/2, height/2 ); cv2drotationmatrix (center, degree, 1.0, & map_matrix); map [2] + = (width_rotate-width)/2; Map [5] + = (height_rotate-height)/2; iplimage * img_rotate = cvcreateimage (cvsize (width_rotate, height_rotate), 8, 3); // perform an affine transform on the image // cv_warp_fill_outliers-fill in the pixels of all output images. // If some pixels fall beyond the boundary of the input image, their values are set to fillval. // transform-specify that map_matrix is the inverse transformation from the output image to the input image. cvwarpaffine (IMG, img_rotate, & map_matrix, cv_inter_linear | cv_warp_fill_outliers, cvscalarall (0); Return img_rot ;}
Practice: rotate and transform the image (Retain the original image content and enlarge the size)-2. Use the cvgetquadranglesubpix function:
// The size of the rotated image remains unchanged, and the size of the image increases accordingly. iplimage * rotateimage2 (iplimage * IMG, int degree) {double angle = degree * cv_pi/180 .; double A = sin (angle), B = cos (angle); int width = IMG-> width, height = IMG-> height; // new image size after rotation int width_rotate = int (height * FABS (A) + width * FABS (B); int height_rotate = int (width * FABS () + height * FABS (B); iplimage * img_rotate = cvcreateimage (cvsize (width_rotate, height_rotate), IMG-> depth, IMG-> nchannels); cvzero (img_rotate ); // minimum size int templength = SQRT (double) width * width + (double) height * Height) + 10; int tempx = (templength + 1) /2-width/2; int Tempy = (templength + 1)/2-height/2; iplimage * temp = cvcreateimage (cvsize (templength, templength), IMG-> depth, IMG-> nchannels); cvzero (temp); // copy the source image to the TMP center of the temporary image cvsetimageroi (temp, cvrect (tempx, Tempy, width, height); cvcopy (IMG, temp, null); cvresetimageroi (temp ); // rotate the array map // [M0 M 1 m2] ==> [A11 A12 B1] // [m3 M4 M5] ==> [A21 A22 B2] float M [6]; int W = temp-> width; int H = temp-> height; m [0] = B; m [1] =; M [3] =-M [1]; m [4] = m [0]; // move the rotation center to the center of the image. M [2] = W * 0.5f; M [5] = H * 0.5f; cvmat M = cvmat (2, 3, cv_32f, m); cvgetquadranglesubpix (temp, img_rotate, & M); cvreleaseimage (& temp ); return img_rotate ;}
Practice: Rado transformation of images (determining the transformation matrix through three points)
Opencv_tutorials in the Reference Manual of opencv 2.3 introduces another method for determining the transformation matrix, which implements transformation through ing of three point transformations.
The transformation is as follows: a transformation matrix can be determined through three points. (The rectangle must be a parallelogram after transformation) The following is the code based on opencv 2.3 (must be supported by at least version 2.0 or later)
Int main () {point2f srctri [3]; point2f dsttri [3]; MAT rot_mat (2, 3, cv_32fc1); MAT warp_mat (2, 3, cv_32fc1); mat src, warp_dst, warp_rotate_dst; // read the image src = imread ("baboon.jpg", 1); warp_dst = mat: zeros (SRC. rows, SRC. cols, SRC. type (); // use three vertices to determine the-affinity transform srctri [0] = point2f (0, 0); srctri [1] = point2f (SRC. cols-1, 0); srctri [2] = point2f (0, SRC. rows-1); dsttri [0] = point2f (SRC. cols * 0.0, SRC. rows * 0.33); dsttri [1] = point2f (SRC. cols * 0.85, SRC. rows * 0.25); dsttri [2] = point2f (SRC. cols * 0.15, SRC. rows * 0.7); warp_mat = getaffinetransform (srctri, dsttri); warpaffine (SRC, warp_dst, warp_mat, warp_dst.size (); // rotate the matrix point center = point (centers/2, degrees/2); double angle =-50.0; double scale = 0.6; rot_mat = getrotationmatrix2d (center, angle, scale); warpaffine (warp_dst, warp_rotate_dst, rot_mat, warp_dst.size ()); /// opencv 1.0 format // iplimage * IMG = cvloadimage ("baboon.jpg"); // iplimage * img_rotate = cvcloneimage (IMG); // cvmat M = warp_mat; // cvwarpaffine (IMG, img_rotate, & M, cv_inter_linear + linear, cvscalarall (0); // cvshowimage ("wrap2", img_rotate); namedwindow ("Source ", cv_window_autosize); imshow ("Source", Src); namedwindow ("Wrap", cv_window_autosize); imshow ("Wrap", warp_dst); namedwindow ("Wrap + rotate ", cv_window_autosize); imshow ("Wrap + rotate", warp_rotate_dst); waitkey (0); Return 0 ;}
Conversion Result:
Reprinted please indicate the source: http://blog.csdn.net/xiaowei_cqu/article/details/7616044
Download lab code: Workshop. Today, I suddenly saw the 2.3 manual and found that the function and basic structure have changed a lot since 2.0, and I still use the 1.0-style function (such as cvmat, cvloadimage ). My two learning tools "Learnning opencv" and "opencv Chinese Reference Manual" are both based on 1.0. This is why I only saw mat today, and then I was amazed. The things summarized by others can help us get started quickly at the beginning, but we need to learn deeply, learn well, and finally work hard to dig for it by ourselves.