通过FCN进行高低肩识别

首先说明对于人的坐姿是否端正,需要就行高低肩识别,

算法流程

1:通过语义分割算法实现人的分割提取(enet,pspnet,fcn,unet等,我们这里使用fcn,因为从c++可以调用呀)

2:图像填充

3;左右肩斜率计算

 

1:c++显示fcn.

需要的文件有pascal-classes.txt,fcn8s-heavy-pascal.prototxt,这两个文件是在opencv-3.4.1的源码中,其它版本有没有,我不知呀。

另外的一个文件是fcn的模型文件fcn8s-heavy-pascal.caffemodel,这个需要单独下载,可以去我的资源里下载(包含上面的两个文件)

直接上代码

#include<opencv2/opencv.hpp>
#include<opencv2/dnn.hpp>
#include<iostream>

using namespace cv;
using namespace std;
using namespace cv::dnn;

const size_t width = 500;
const size_t height = 500;//定义图像文件宽高

vector<Vec3b> labels_color();

string label_file = "F:/fcn/pascal-classes.txt";
string deploy_file = "F:/fcn/fcn8s-heavy-pascal.prototxt";
string model_file = "F:/fcn/fcn8s-heavy-pascal.caffemodel";



int main(int argc, char **argv)
{
	Mat src = imread("F:/fcn/FT20A1180801279223.jpg");

	if (!src.data)
	{
		cout << "图像文件未找到!!!" << endl;
		return -1;
	}
	resize(src, src, Size(500, 500), 0, 0);
	vector<Vec3b>colors = labels_color();
	Net net;
	net = readNetFromCaffe(deploy_file, model_file);//读取二进制文件和描述文件
	float t1 = getTickCount();
	Mat inputblob = blobFromImage(src);
	net.setInput(inputblob, "data");
	Mat score = net.forward("score");
	float t2 = getTickCount();
	float t = (t2 - t1) / getTickFrequency();
	cout << "运行时间:" << t << endl;

	const int rows = score.size[2];   //图像的高
	const int cols = score.size[3];   //图像的宽
	const int chns = score.size[1];   //图像的通道数
	Mat maxCl(rows, cols, CV_8UC1);
	Mat maxVal(rows, cols, CV_32FC1);

	for (int c = 0; c < chns; c++) {
		for (int row = 0; row < rows; row++) {
			const float *ptrScore = score.ptr<float>(0, c, row);
			uchar *ptrMaxCl = maxCl.ptr<uchar>(row);
			float *ptrMaxVal = maxVal.ptr<float>(row);
			for (int col = 0; col < cols; col++) {
				if (ptrScore[col] > ptrMaxVal[col]) {
					ptrMaxVal[col] = ptrScore[col];
					ptrMaxCl[col] = (uchar)c;
				}
			}
		}
	}

	// look up colors
	Mat result = Mat::zeros(rows, cols, CV_8UC3);
	for (int row = 0; row < rows; row++) {
		const uchar *ptrMaxCl = maxCl.ptr<uchar>(row);
		Vec3b *ptrColor = result.ptr<Vec3b>(row);
		for (int col = 0; col < cols; col++) {
			ptrColor[col] = colors[ptrMaxCl[col]];
		}
	}
	Mat dst;
	addWeighted(src, 0.3, result, 0.7, 0, dst);  //图像合并
	imshow("FCN-demo", dst);

	waitKey(0);
	destroyAllWindows();
	return 0;

}

vector<Vec3b> labels_color()
{
	vector<Vec3b>colors;


	ifstream fp(label_file);//打开输入流,读入文件
	if (!fp.is_open())
	{
		printf("文件读入失败!!!\n");
		exit(-1);//直接退出

	}
	string names;
	int temp;
	Vec3b color;
	string line;//标签文件中都有对应的名字
	while (!fp.eof())//当文件没有读到结尾
	{
		getline(fp, line);//读取每一行
		stringstream ss(line); //分割字符串
		ss >> names; //读的第一个字符串是names
		ss >> temp;
		color[0] = temp;  //读一个字符串就给color
		ss >> temp;
		color[1] = temp;
		ss >> temp;
		color[2] = temp;
		colors.push_back(color);

	}
	return colors;
}




看一下结果:

 

效果一般,没关系,自己找人的分割数据集,对fcn进行重新训练(具体不在展示)

3:肩部斜率计算代码


		int row = FO_m_sssroi1.rows;//获取行数	
		int col = FO_m_sssroi1.cols*FO_m_sssroi1.channels();//注意是列数*通道数	
		int sum = 0;
		int sum_1 = 0;
		int Zsum = 0;
		int Zsum_1 = 0;
		float the_first_col;
		float the_end_col;
		float the_Zfirst_col;
		float the_Zend_col;
		float co_1;
		float Zco_1;
		//cout << row << "," << col << endl;
		//ofstream ofs("pixel.txt");	
		for (int i = 0; i < row; ++i)
		{
			uchar *data1 = FO_m_sssroi1.ptr<uchar>(i);//获取第i行首地址	
			uchar *data_1 = FO_m_sssroi_1.ptr<uchar>(i);//获取第i行首地址	
			uchar *Zdata1 = ZO_m_sssroi1.ptr<uchar>(i);//获取第i行首地址	
			uchar *Zdata_1 = ZO_m_sssroi_1.ptr<uchar>(i);//获取第i行首地址
			if (sum<int(*data1))
			{
				the_first_col = i;
			}
			if (sum_1<int(*data_1))
			{
				the_end_col = i;
			}
			if (Zsum<int(*Zdata1))
			{
				the_Zfirst_col = i;
			}
			if (Zsum_1<int(*Zdata_1))
			{
				the_Zend_col = i;
			}
			sum = int(*data1);
			sum_1 = int(*data_1);
			Zsum = int(*Zdata1);
			Zsum_1 = int(*Zdata_1);
			data1++;
			data_1++;
			Zdata1++;
			Zdata_1++;
		}
		//ofs << "*******************************************************************" << endl;
		co_1 = (the_end_col - the_first_col) / (w / 6 - 4 - 1);
		Zco_1 = (the_Zend_col - the_Zfirst_col) / (w / 6 - 4 - 1);
		float atanValue2 = atan(co_1)*180.0f / PI;//肩部的角度
		float atanValue3 = atan(Zco_1)*180.0f / PI;//肩部的角度
		cout << "右肩倾斜角度为!" << atanValue2 << "°" << "右肩高度为!" << (the_end_col + the_first_col) / 2 << endl;
		cout << "左肩倾斜角度为!" << abs(atanValue3) << "°" << "左肩高度为!" << (the_Zend_col + the_Zfirst_col) / 2 << endl;
		cout << "plaese open hear" << atanValue2 << endl;
		result += "\"zjiaodu\": " + to_string(atanValue2) + ",";
		result += "\"yjiaodu\": " + to_string(abs(atanValue3));

代码简单说明;

通过分割位置与矩形位置相交的两点求出斜率,也就是肩部角度。分割模型速度太慢,需要优化,选用unet(下章)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值