1. 仿射變換
可將圖片變換爲平行四邊形
/**@brief從三對對應點計算仿射變換。
@param src[] :原圖上取三點座標(三角形)
@param dst[] :目標三點座標
@param return :返回2*3的變換矩陣
*/
CV_EXPORTS Mat getAffineTransform( const Point2f src[], const Point2f dst[] );
/ ** @brief對圖像應用仿射變換。
函數warpAffine使用指定的矩陣轉換源圖像:
@param src輸入圖像。
@param dst輸出圖像,其大小爲dsize,並且與src類型相同。
@param M \ f $ 2 \ times 3 \ f $轉換矩陣。
@param dsize輸出圖像的大小。
@param標誌插值方法( 詳見 結構定義)
@param borderMode像素外推方法( 詳見 結構定義)
borderMode =#BORDER_TRANSPARENT,表示目標圖像中的像素對應於源圖像中的“異常值”不會被該功能修改。
@param borderValue邊界不變時使用的值;默認情況下爲0。
@sa warpPerspective,調整大小,重新映射,getRectSubPix,轉換
*/
CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
2. 旋轉
/ ** @brief計算2D旋轉的仿射矩陣。
@param center源圖像中旋轉的中心。
@param angle旋轉角度,以度爲單位。 正值表示逆時針旋轉(座標原點假定爲左上角)。
@param scale各向同性比例因子。
@sa getAffineTransform,warpAffine,變換
* /
CV_EXPORTS_W Mat getRotationMatrix2D( Point2f center, double angle, double scale );
2.1 demo
int MPT_test_warpAffine(std::string file)
{
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;
// 加載源圖像
src = imread(file, 1);
// 設置目標圖像的大小和類型與源圖像一致
warp_dst = Mat::zeros(src.rows, src.cols, src.type());
// 設置源圖像和目標圖像上的三組點以計算仿射變換
srcTri[0] = cv::Point2f(0, 0);
srcTri[1] = cv::Point2f(src.cols - 1, 0);
srcTri[2] = cv::Point2f(0, src.rows - 1);
dstTri[0] = cv::Point2f(0, 0);
dstTri[1] = cv::Point2f(src.cols - 1, src.rows * 0.5);
dstTri[2] = cv::Point2f(0, src.rows * 0.5);
// 求得仿射變換
warp_mat = getAffineTransform(srcTri, dstTri);
// 對源圖像應用上面求得的仿射變換
warpAffine(src, warp_dst, warp_mat, warp_dst.size());
/** 對圖像扭曲後再旋轉 */
// 計算繞圖像中點順時針旋轉50度縮放因子爲0.6的旋轉矩陣
Point center = Point(warp_dst.cols / 2, warp_dst.rows / 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());
// 顯示結果
namedWindow("src", CV_WINDOW_NORMAL);
namedWindow("warp", CV_WINDOW_NORMAL);
namedWindow("warp_rotate", CV_WINDOW_NORMAL);
imshow("src", src);
imshow("warp", warp_dst);
imshow("warp_rotate", warp_rotate_dst);
waitKey(0);
return 0;
}
3. 透視變換
可將矩形圖片變換成梯形
根據4組點變換 返回3*3矩陣
CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] );
/ ** @brief將透視轉換應用於圖像。
@param src輸入圖像。
@param dst輸出圖像,其大小爲dsize,並且與src類型相同。
@param M \ f $ 3 \ times 3 \ f $轉換矩陣。
@param dsize輸出圖像的大小。
@param標誌插值方法
@param borderMode像素外推方法(#BORDER_CONSTANT或#BORDER_REPLICATE)。
@param borderValue邊界不變時使用的值;默認情況下,它等於0。
@sa warpAffine,調整大小,重新映射,getRectSubPix,perspectiveTransform
* /
CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
3.1 demo
int MPT_test_warpPerspective(std::string file)
{
Point2f srcTri[4];
Point2f dstTri[4];
Mat warpPerspective_mat(3, 3, CV_32FC1);
Mat src, warpPerspective_dst;
// Load the image
src = imread(file, IMREAD_COLOR);
// Set the dst image the same type and size as src
warpPerspective_dst = Mat::zeros(src.rows, src.cols, src.type());
// 設置四組點,求出變換矩陣
srcTri[0] = Point2f(0, 0);
srcTri[1] = Point2f(src.cols - 1, 0);
srcTri[2] = Point2f(0, src.rows - 1);
srcTri[3] = Point2f(src.cols - 1, src.rows - 1);
dstTri[0] = Point2f(0, src.rows * 0.13);
dstTri[1] = Point2f(src.cols * 0.9, 0);
dstTri[2] = Point2f(src.cols * 0.2, src.rows * 0.7);
dstTri[3] = Point2f(src.cols * 0.8, src.rows);
warpPerspective_mat = getPerspectiveTransform(srcTri, dstTri);
//透視變換
warpPerspective(src, warpPerspective_dst, warpPerspective_mat, src.size());
namedWindow("src", 0);
imshow("src", src);
namedWindow("warpPerspective", 0);
imshow("warpPerspective", warpPerspective_dst);
waitKey(0);
return 0;
}
4. 彎曲
4.1 S形狀
int MPT_test_S_change(std::string file) {
double RANGE = 1000;
double PI = 3.1415926;
Mat src = imread(file, IMREAD_COLOR);
Mat dst(src.rows, src.cols, CV_8UC3, Scalar(0));
for (int i = 0; i < dst.rows; i++) {
double temp = (dst.cols - RANGE) / 2 + (dst.cols - RANGE) * sin((2 * PI * i) / dst.rows + PI) / 2;
for (int j = int(temp + 0.5); j < RANGE + temp; j++) {
int m = (int)((j - temp) * (src.cols) / RANGE);
if (m >= src.cols)
m = src.cols - 1;
if (m < 0)
m = 0;
dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, m)[0];
dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, m)[1];
dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, m)[2];
}
}
namedWindow("S形變形", CV_WINDOW_NORMAL);
imshow("S形變形", dst);
cv::waitKey(0);
return 0;
}
4.2 波浪形
int MPT_test_2S_change(std::string file) {
double RANGE = 100;
double PI = 3.1415926;
Mat src = imread(file, IMREAD_COLOR);
Mat dst(src.rows, src.cols, CV_8UC3, Scalar(0));
for (int j = 0; j < dst.cols; j++) {
double temp = RANGE + RANGE * sin(j * PI * 2 / dst.cols);//利用sin函數得到一段正弦波,將圖像映射到兩個正弦波中即得到波浪形
for (int i = int(temp); i < dst.rows + temp - 2 * RANGE; i++) {
int m = (int)((i - temp) * (src.rows) / (dst.rows - RANGE));
if (m >= src.rows)
m = src.rows - 1;
if (m < 0)
m = 0;
dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(m, j)[0];
dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(m, j)[1];
dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(m, j)[2];
}
}
namedWindow("波浪變形", CV_WINDOW_NORMAL);
imshow("波浪變形", dst);
cv::waitKey(0);
return 0;
}
5. 魚眼特效
int MPT_test_fish_change(std::string file) {
double PI = 3.1415926;
Mat src = imread(file, IMREAD_COLOR);
cv::resize(src, src, Size(1080, 1080));
Mat dst(src.rows, src.cols, CV_8UC3, Scalar(0));
for (int id = 0; id < dst.rows; id++) {
for (int jd = 0; jd < dst.cols; jd++) {
double xd = jd * 2.0 / dst.cols - 1.0;
double yd = id * 2.0 / dst.cols - 1.0;
double rd = sqrt(xd * xd + yd * yd);
double phid = atan2(yd, xd);
double xs = asin(rd) * 2 / PI * cos(phid);
double ys = asin(rd) * 2 / PI * sin(phid);
int is = round((ys + 1.0) * dst.rows / 2.0);
int js = round((xs + 1.0) * dst.cols / 2.0);
if (is > dst.rows || is < 0 || js>dst.cols || js < 0)
continue;
dst.at<Vec3b>(id, jd)[0] = src.at<Vec3b>(is, js)[0];
dst.at<Vec3b>(id, jd)[1] = src.at<Vec3b>(is, js)[1];
dst.at<Vec3b>(id, jd)[2] = src.at<Vec3b>(is, js)[2];
}
}
cv::resize(dst, dst, Size(1080, 720));
cv::namedWindow("魚眼特效", CV_WINDOW_NORMAL);
cv::imshow("魚眼特效", dst);
cv::imwrite("../image/fisheye.jpg", dst);
cv::waitKey(0);
return 0;
}
6. 結構定義
enum BorderTypes {
BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i`
BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb`
BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg`
BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`
BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_ISOLATED = 16 //!< do not look outside of ROI
};
enum InterpolationFlags{
/** nearest neighbor interpolation */
INTER_NEAREST = 0,
/** bilinear interpolation */
INTER_LINEAR = 1,
/** bicubic interpolation */
INTER_CUBIC = 2,
/** resampling using pixel area relation. It may be a preferred method for image decimation, as
it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST
method. */
INTER_AREA = 3,
/** Lanczos interpolation over 8x8 neighborhood */
INTER_LANCZOS4 = 4,
/** Bit exact bilinear interpolation */
INTER_LINEAR_EXACT = 5,
/** mask for interpolation codes */
INTER_MAX = 7,
/** flag, fills all of the destination image pixels. If some of them correspond to outliers in the
source image, they are set to zero */
WARP_FILL_OUTLIERS = 8,
/** flag, inverse transformation
For example, #linearPolar or #logPolar transforms:
- flag is __not__ set: \f$dst( \rho , \phi ) = src(x,y)\f$
- flag is set: \f$dst(x,y) = src( \rho , \phi )\f$
*/
WARP_INVERSE_MAP = 16
};
結構定義(中文)
enum InterpolationFlags {
/**最近鄰插值*/
INTER_NEAREST = 0,
/**雙線性插值*/
INTER_LINEAR = 1
/**雙三次插值*/
INTER_CUBIC = 2
/**使用像素面積關係重新採樣。它可能是圖像抽取的首選方法,因爲它提供無雲紋的結果。但是當圖像放大時,它類似於INTER_NEAREST方法。 */
INTER_AREA = 3,
/**在8x8鄰域上進行Lanczos插值*/
INTER_LANCZOS4 = 4
/**位精確雙線性插值*/
INTER_LINEAR_EXACT = 5
/**內插代碼的掩碼*/
INTER_MAX = 7
/**標誌,填充所有目標圖像像素。如果其中一些對應於源圖像,它們設置爲零*/
WARP_FILL_OUTLIERS = 8
/** 標誌,逆變換例如,#linearPolar或#logPolar轉換爲:-__not__標誌未設置:\ f $ dst(\ rho,\ phi)= src(x,y)\ f $-設置了標誌:\ f $ dst(x,y)= src(\ rho,\ phi)\ f $ */
WARP_INVERSE_MAP = 16
};
參考文檔
參考文檔