opencv圖片變形 仿射 旋轉 透視 彎曲 魚眼特效

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
};

參考文檔

參考文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章