OpenCV-C++-CUDA-07-基于颜色的物体跟踪

        上一篇OpenCV-C++—CUDA-06-形态学二值化操作展示了二值图像、形态学在OpenCV-CUDA版本上的示例。本章我使用HSV颜色提取,以及形态学操作、联通区域来跟踪物体(跟踪下面偏黄色的小球)。

在这里插入图片描述
先给一张inRange颜色过滤表:

绿
hmin0000,15611263578100125
hmax18018018010 ,18025347799124155
smin00043434343434343
smax2554330255255255255255255255
vmin04622146464646464646
vmax46220255255255255255255255255

大致步骤是:
1)BGR转HSV;
2)通道分离;
3)根据颜色表求出h、s、v阈值;
4)求出h、s、v交集;
5)形态学去噪点(先开后闭操作/膨胀);
6)联通组件分析定位。

相关代码:

#include<opencv2/opencv.hpp>
#include<opencv2/cudaimgproc.hpp>

using namespace std;
using namespace cv;

int main(int argc, char ** argv)
{
	VideoCapture cap(0);
	cap.open("F:\\test\\images_jia\\balltest.mp4");
	Mat frame,result,dst;
	cuda::GpuMat frame_gpu,hsv,mask;
	vector<cuda::GpuMat>mv;
	vector<cuda::GpuMat>thres(4);
	while (true)
	{
		bool ret=cap.read(frame);
		if (!ret)
		{
			break;
		}
		//imshow("input video", frame);
		double t1 = getTickCount();
		frame_gpu.upload(frame);
		cuda::cvtColor(frame_gpu, hsv,COLOR_BGR2HSV);//BGR->HSV
		//通道分离(cuda版本没有inRange()方法)
		cuda::split(hsv, mv);

		/*黄色26-34的h通道就被提取出来了*/
		cuda::threshold(mv[0], thres[0], 26, 255, THRESH_BINARY);
		cuda::threshold(mv[0], thres[3], 34, 255, THRESH_BINARY);
		//============
		cuda::threshold(mv[1], thres[1], 43, 255, THRESH_BINARY);
		cuda::threshold(mv[2], thres[2], 46, 255, THRESH_BINARY);

		cuda::bitwise_xor(thres[0], thres[3],thres[0]);//异或

		//求它们三个的交集
		cuda::bitwise_and(thres[1], thres[0], mask);
		cuda::bitwise_and(mask, thres[2], mask);
		//cuda::threshold(mask, mask, 100, 255, THRESH_BINARY);
		//形态学操作
		Mat se_open = cv::getStructuringElement(MORPH_RECT, Size(5, 5));
		Mat se_close = cv::getStructuringElement(MORPH_RECT, Size(11,11));
		auto morpy_open=cuda::createMorphologyFilter(MORPH_OPEN, mask.type(), se_open);//开操作
		morpy_open->apply(mask, mask);
		auto morpy_close = cuda::createMorphologyFilter(MORPH_CLOSE, mask.type(), se_close);//闭操作
		morpy_close->apply(mask, mask);
		//膨胀
		//auto dilate=cuda::createMorphologyFilter(MORPH_DILATE, mask.type(), se_close);//膨胀
		//dilate->apply(mask, mask);
		mask.download(result);
		//联通组件分析
		Mat labels = Mat::zeros(mask.size(), CV_32S);

		Mat stats, centroids; //状态、中心
		int num_labels = cv::connectedComponentsWithStats(result, labels, stats, centroids, 4, 4);
		for (int i = 1; i < num_labels; i++) //i=0时,是背景
		{
			//中心点坐标
			int cx = centroids.at<double>(i, 0);
			int cy = centroids.at<double>(i, 1);
			//从状态里获取矩形坐标
			int x = stats.at<int>(i, CC_STAT_LEFT);
			int y = stats.at<int>(i, CC_STAT_TOP);
			int width = stats.at<int>(i, CC_STAT_WIDTH);
			int height = stats.at<int>(i, CC_STAT_HEIGHT);
			if (width < 40 || height < 40) //过滤面积小的区域
			{
				continue;
			}
			circle(frame, Point(cx, cy), 3, Scalar(0, 0, 255), 2, 8, 0);
			rectangle(frame, Point(x, y), Point(x + width, y + height), Scalar(0, 255, 0), 2, 8, 0);
		}

		
		double fps = getTickFrequency() / (getTickCount() - t1);
		putText(frame, format("FPS:%.2f", fps), Point(50, 50), FONT_HERSHEY_PLAIN, 1.5, Scalar(0, 0, 255), 2, 8);
		imshow("input video", frame);
		imshow("result", result);
		char c = waitKey(10);
		if (c == 27)
		{
			break;
		}
	}
	cv::destroyAllWindows();
	return 0;
}

结果:
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值