opencv4.2旋转图片后去除黑边 保留透明

环境: win + opencv4.2 + visual studio 2017

先看效果图,旋转后四个角多余部分为透明状态:
在这里插入图片描述
方法1:
计算旋转后的图片的宽高,然后遍历原图像素点拷贝到旋转后的图相应位置。注意:imread的最后一个参数IMREAD_UNCHANGED表示带有alpha通道。也就是 原图Mat必须是4通道(BGRA)。

Mat RotateBGRA_Mat(cv::Mat img, float angle)
{
	double a = sin(angle  * CV_PI / 180);
	double b = cos(angle  * CV_PI / 180);
	int width = img.cols;
	int height = img.rows;
	int width_rotate = int(height * fabs(a) + width * fabs(b));//旋转后的宽
	int height_rotate = int(width * fabs(a) + height * fabs(b));旋转后的高

	Mat retMat = Mat::zeros(Size(width_rotate, height_rotate), CV_8UC4);
	float anglePI = angle * CV_PI / 180;
	int xSm, ySm;

	for (int i = 0; i < retMat.rows; i++)
		for (int j = 0; j < retMat.cols; j++)
		{
			xSm = (int)((i - retMat.rows / 2)*cos(anglePI) - (j - retMat.cols / 2)*sin(anglePI) + 0.5);
			ySm = (int)((i - retMat.rows / 2)*sin(anglePI) + (j - retMat.cols / 2)*cos(anglePI) + 0.5);
			xSm += img.rows / 2;
			ySm += img.cols / 2;

			if (xSm >= img.rows || ySm >= img.cols || xSm <= 0 || ySm <= 0) {
				retMat.at<Vec4b>(i, j) = Vec4b(0, 0);
			}
			else {
				retMat.at<Vec4b>(i, j) = img.at<Vec4b>(xSm, ySm);
			}
		}
	return retMat;
}

int main()
{
    int rotation = 30;
    Mat r_mat = imread("xxx\\p.png", IMREAD_UNCHANGED);

    //1 when Mat is with alpha channel(BGRA)
    Mat dstMat = RotateBGRA_Mat(r_mat, rotation);
    imwrite("D:\\s.png", dstMat);
}

方法2:
对于没有alpha通道的图片,可手动去掉某个颜色使其透明。

const int color_drop = 20;
struct ForEachOperator
{
	void operator ()(cv::Vec4b &pixel, const int *position) const
	{
		if (pixel[0] <= color_drop && pixel[1] <= color_drop && pixel[2] <= color_drop)
			pixel[3] = 0;
	}
};

Mat RotateBGR_Mat(cv::Mat img, float angle)
{
	double a = sin(angle  * CV_PI / 180);
	double b = cos(angle  * CV_PI / 180);
	int width = img.cols;
	int height = img.rows;
	int width_rotate = int(height * fabs(a) + width * fabs(b));//旋转后的宽
	int height_rotate = int(width * fabs(a) + height * fabs(b));旋转后的高

	Mat retMat = Mat::zeros(Size(width_rotate, height_rotate), CV_8UC3);
	float anglePI = angle * CV_PI / 180;
	int xSm, ySm;

	for (int i = 0; i < retMat.rows; i++)
		for (int j = 0; j < retMat.cols; j++)
		{
			xSm = (int)((i - retMat.rows / 2)*cos(anglePI) - (j - retMat.cols / 2)*sin(anglePI) + 0.5);
			ySm = (int)((i - retMat.rows / 2)*sin(anglePI) + (j - retMat.cols / 2)*cos(anglePI) + 0.5);
			xSm += img.rows / 2;
			ySm += img.cols / 2;

			if (xSm >= img.rows || ySm >= img.cols || xSm <= 0 || ySm <= 0) {
				retMat.at<Vec3b>(i, j) = Vec3b(0, 0);
			}
			else {
				retMat.at<Vec3b>(i, j) = img.at<Vec3b>(xSm, ySm);
			}
		}
	return retMat;
}
int main()
{
    int rotatio
    n = 30;
    Mat r_mat = imread("xxx\\p.png");
    Mat input_bgra;
	Mat dstMat = RotateBGR_Mat(r_mat, rotation);
	cvtColor(dstMat, input_bgra, CV_BGR2BGRA);
	input_bgra.forEach<Vec4b>(ForEachOperator());
	imwrite("D:\\ss.png", input_bgra);
}

方法3:
注意:原图Mat也必须是4通道(BGRA),否则四周多余部分将出现黑边

int main()
{
        int rotation = 30;
        //The Mat is must with alpha channel(BGRA)
        Mat r_mat3= imread("xxx\\p.png",IMREAD_UNCHANGED);
        
		double a = sin(rotation  * CV_PI / 180);
		double b = cos(rotation  * CV_PI / 180);
		int width = r_mat3.cols;
		int height = r_mat3.rows;
		int width_rotate = int(height * fabs(a) + width * fabs(b));//旋转后的宽
		int height_rotate = int(width * fabs(a) + height * fabs(b));旋转后的高

		Point center = Point(r_mat3.cols / 2, r_mat3.rows / 2);// 旋转中心

		Mat map_matrix = getRotationMatrix2D(center, rotation, 1.0);
		map_matrix.at<double>(0, 2) += (width_rotate - width) / 2;     // 修改坐标偏移
		map_matrix.at<double>(1, 2) += (height_rotate - height) / 2;   // 修改坐标偏移
		Mat rotateImg;
		warpAffine(r_mat3, rotateImg, map_matrix, { width_rotate, height_rotate });
		imwrite("D:\\sss.png", rotateImg);
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值