当前位置:   article > 正文

Opencv 图像等比例缩放_cv2等比例缩放原图

cv2等比例缩放原图

神经网络训练过程中,会使用到大量的数据预处理操作。而缩放操作就是这里面最基础。例如Certernet中的缩放就是使用了等比例缩放,周围填充0的操作。

我们来分析下实现原理和实际效果

在这里插入图片描述
如上图所示,是将[600,543的图片]等比例缩放为[352,352],边界填充黑色。这样做的好处,是图片不会有变形压缩,使得训练的时候网络输入的图片,更解决与现实中的图像。

实际场景中,图片的变形压缩并不影响图像的检查效果; 这种压缩方式的目的主要是为了在设备端实现推理时,与训练时保持预处理的一致,提高检出率。

warpAffine

以上效果的实现,是通过cv2.warpAffine方法实现的。该方法的参数为

cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
  • 1

src - 输入图像。
M - 变换矩阵。
dsize - 输出图像的大小。
flags - 插值方法的组合(int 类型!)
borderMode - 边界像素模式(int 类型!)
borderValue - (重点!)边界填充值; 默认情况下,它为0。

在这里,我们需要重点获取M变换矩阵

getAffineTransform

变换矩阵是通过

cv2.getAffineTransform(np.float32(dst), np.float32(src))
  • 1

src - 输入图像的三个坐标点
dst - 目标图像的三个坐标点

我们看下等比例缩放时,输入图形的三个坐标点和输出图像的三个坐标点的计算公式

在这里插入图片描述
其中,在原图中

//图像中心点
src_cen = (src_w/2, src_h/2)
max_src_cen = max(src_w/2, src_h/2)
a0 = (src_cen.x,src_cen.y)
a1 = (src_cen.x,src_cen.y-max_src_cen)
a2 = (src_cen.x-max_src_cen, src_cen.y)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

同理,目标图像中:

//图像中心点
dst_cen = (dst_w/2, dst_h/2)
max_det_cen = max(dst_w/2, dst_h/2)
a0 = (dst_cen.x,dst_cen.y)
a1 = (dst_cen.x,dst_cen.y-max_det_cen)
a2 = (dst_cen.x-max_det_cen, dst_cen.y)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

三个点的相对位置的宽和高分别与图形的宽和高对应,也就是将三个坐标点的空间关系与图像的宽和高进行绑定,以此达到使用getAffineTransform的时候,能够等比例缩放图片

源码

以下是c++的实现,python的实现,可以参考centernet工程centernet

#include <opencv2\opencv.hpp>

struct CenterScale
{
	cv::Mat input;
	cv::Point2f center;
	cv::Point2f scale;
	float r = 0;
};

cv::Point2f get_dir(cv::Point2f src_point, float rot_rad)
{
	float sn = sin(rot_rad);
	float cs = cos(rot_rad);
	float src_result[2] = { 0, 0 };
	src_result[0] = src_point.x * cs - src_point.y * sn;
	src_result[1] = src_point.x * sn + src_point.y * cs;
	return{ src_result[0], src_result[1] };
}
cv::Mat  get_affine_transform(cv::Point2f center, cv::Point2f scale, float rot,
	int output_size[], bool inv)
{
	float scale_tmp = scale.x;
	float src_w = scale_tmp;
	float dst_w = (float)output_size[0];
	float dst_h = (float)output_size[1];


	float half_1 = 0.5;
	float shift[2] = { 0, 0 };
	float rot_rad = 3.1415926 * rot / 180;
	cv::Point2f src_point = { 0, src_w * -half_1 };

	cv::Point2f src_dir = get_dir(src_point, rot_rad);

	cv::Point2f dst_dir = { 0, dst_w * -half_1 };

	cv::Point2f src[3];
	cv::Point2f dst[3];

	src[0] = { center.x + scale_tmp * shift[0], center.y + scale_tmp * shift[1] };
	src[1] = { center.x + src_dir.x + scale_tmp * shift[0], center.y + src_dir.y + scale_tmp * shift[1] };

	dst[0] = { dst_w * half_1, dst_h * half_1 };
	dst[1] = { dst_w * half_1 + dst_dir.x, dst_h * half_1 + dst_dir.y };

	src[2] = get_3rd_point(src[0], src[1]);
	dst[2] = get_3rd_point(dst[0], dst[1]);

	cv::Mat trans;
	if (inv)
	{
		trans = cv::getAffineTransform(dst, src);
	}
	else
	{
		trans = cv::getAffineTransform(src, dst);
	}
	return trans;
}


CenterScale getAffineTransImage(const cv::Mat& img, int network_input_size[])
{

	int width = img.cols;
	int height = img.rows;

	CenterScale center_scale;
	center_scale.center = { width / (float)2.0, height / (float)2.0 };
	float s = std::max(height, width)*1.0;
	center_scale.scale = { s, s };

	float rolate = 0;

	cv::Mat trans = get_affine_transform(center_scale.center, center_scale.scale, rolate, network_input_size, false);

	cv::Mat transed_dstImage(network_input_size[0], network_input_size[1], img.type());
	cv::warpAffine(img, transed_dstImage, trans, transed_dstImage.size());


	CenterScale meta;
	meta.input = transed_dstImage;
	meta.center = center_scale.center;
	meta.scale = center_scale.scale;
	meta.r = 0.0;
	return meta;

}
cv::Point2f get_3rd_point(cv::Point2f a, cv::Point2f b)
{
	cv::Point2f direct = { a.x - b.x, a.y - b.y };
	direct = { b.x - direct.y, b.y + direct.x };
	return direct;
}
int main()

{
	cv::Mat input = cv::imread("G://VS2013//Ai_Demo//images//person.jpg"); 
	int network_input_size[2] = { 352, 352 };
	CenterScale meta = getAffineTransImage(input, network_input_size);
	cv::imwrite(meta.input);
	return 0;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/273813?site
推荐阅读
相关标签
  

闽ICP备14008679号