后续角度等计算

一、calculateAngle

double calculate_angle_3FPoint(const SDL_FPoint& a, const SDL_FPoint& b, const SDL_FPoint& c)
图1 calculate_angle_3FPoint计算三点角度

calculate_angle_3FPoint(a, b, c) 计算的是以b为顶点的角∠ABC,即向量BA和BC之间的夹角。调用时需填对参数b,互换参数a和c不影响结果。。

check_raised_hands负责提取手臂的关键点,并计算左右手臂的弯曲角度。用的是两次calculate_angle_3FPoint,调用时需填对b,用左右肘(elbow)。

void check_raised_hands(const SDL_FPoint* landmarks, double& left_arm_angle, double& right_arm_angle)
{
	// Left arm angle detection
	const SDL_FPoint& l_shoulder = landmarks[11];
	const SDL_FPoint& l_elbow = landmarks[13];
	const SDL_FPoint& l_wrist = landmarks[15];
	double left_arm_rad = calculate_angle_3FPoint(l_shoulder, l_elbow, l_wrist);
 
	left_arm_angle = RAD2DEG(left_arm_rad);
 
	// Right arm angle detection
	const SDL_FPoint& r_shoulder = landmarks[12];
	const SDL_FPoint& r_elbow = landmarks[14];
	const SDL_FPoint& r_wrist = landmarks[16];
	double right_arm_rad = calculate_angle_3FPoint(r_shoulder, r_elbow, r_wrist);
	right_arm_angle = RAD2DEG(right_arm_rad);
}

 

二、imgcoor_calculate_angle_2p + angles::normalize_angle_positive

图2 计算两点角度

联合这两个函数,可计算二维向量AB(图像坐标系)与X轴正方向的夹角,并将其归一化到 [0, 2π) 范围。AB长度小于1e-10时,得到是0度。

参数(start_x、start_y)是向量AB中的起点A,参数(end_x、end_y)是终点B。不能互换,一旦互换,可看图2,值完全变了。

double imgcoor_calculate_angle_2p(double start_x, double start_y, double end_x, double end_y)
{
	double deltax = end_x - start_x;
	double deltay = end_y - start_y;

	if (fabs(deltax) < 1e-10 && fabs(deltay) < 1e-10) {
		// 若 x 和 y 同时为 0,atan2 的结果未定义,由库实现决定。例如 MSVC 通常返回 0。
		return 0;		
	}

	double theta = atan2(deltay, deltax);

	// atan2 的返回值:>0 表示逆时针,<0 表示顺时针,这符合数学规则。
	// 但 @start_x/start_y、@end_x/end_y 是图像坐标,其 Y 轴方向与数学坐标相反。
	// 因此乘以 -1 来修正,使最终角度遵循数学惯例:
	// >0 表示逆时针,<0 表示顺时针。
	return -1 * theta;
}

imgcoor_calculate_angle_2p得到[-π, π),这角度正负和数学课教的一样,即逆时针是正,顺时针是负。

normalize_angle_positive负责把范围归一化到[0, 2π) 。

 

全部评论: 0

    写评论: