C++/OpenCV实现图像目标识别与分类

写在前面

这次分享的为一个很理想的情况下的目标识别与分类,对象为螺丝、螺帽、圆环这三个东西,其实就是图一乐呵,为什么说理想化呢?看一下本文使用的实验图片。
在这里插入图片描述
可以看到,图像中三个目标非常清楚,因为该图背景非常单一,这张图为在我床单上拍的。最近也还在补充图像处理相关的数学基础理论,要达到能在复杂背景下的目标检测与识别,需要学习的地方还很多。

方法流程

  1. 图像预处理,包括去噪、去除背景、阈值化
  2. 图像分割
  3. 特征提取
  4. 机器分类学习

下面根据该顺序具体介绍相关代码以及效果。

1.图像预处理

首先是去除噪声,本文使用高斯滤波去噪。然后是去除背景,在这一步骤由于图像是理性化环境下拍摄的,所以特别好处理,只需要用大核卷积模糊图像来而得到背景图,然后使用图片与背景图进行差分,就可以达到背景去除的目的。最后是阈值化,选取阈值将图像变为二值图像,便于图像分割。

//获得背景图像
cv::Mat calculateLightPattern(cv::Mat img)
{
   
	cv::Mat pattern;
	//通过使用相对于图像大小的大内核尺寸模糊得到背景图
	blur(img, pattern, cv::Size(img.cols / 3, img.cols / 3));
	return pattern;
}
//移除背景
cv::Mat removeLight(cv::Mat img, cv::Mat pattern)
{
   
	cv::Mat result;
	cv::Mat img32, pattern32;
	img.convertTo(img32, CV_32F);
	pattern.convertTo(pattern32, CV_32F);
	//通过背景图像移除背景
	result = 1 - (pattern32/img32);
	result = result * 255;
	result.convertTo(result, CV_8U);
	/*result = img-pattern;*/
	return result;
}

以上为预处理阶段需要的子函数,在预处理函数中将两个函数调用

//预处理
cv::Mat preprocessImage(cv::Mat input)
{
   
	cv::Mat result;
	//去噪
	cv::Mat img_noise;
	GaussianBlur(input, img_noise, cv::Size(5, 5), 0, 0);

	//去除背景
	cv::Mat img_no_light;
	cv::Mat light_pattern = calculateLightPattern(img_noise);
	img_no_light = removeLight(img_noise, light_pattern);

	//阈值化处理
	threshold(img_no_light, result, 30, 255, cv::THRESH_BINARY);

	return result;
}

在目标检测函数中调用,结果如下所示(第一幅图为灰度图像,第二幅图为通过图像模糊得到的背景图,第三幅图为通过背景图将灰度图像背景之后的结果图。得到结果图后阈值化,得到第四幅图):
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.图像分割

本文中采用连通组件算法进行图像分割。因为上述操作已经将图像转为二值图像,采用八个或者四个连接像素来标记图像。如果两个像素具有相同的值并且是邻居,则把他们连接起来。得到一个个对象就是识别出来的结果,下面是图像识别函数

int targetDectation(std::string path)
{
   
	//读取图像
	cv::Mat imageGray,imageRGB = cv::imread(path, cv::IMREAD_COLOR);
	if (imageRGB.empty())
	{
   
		std::cout << "Fail to read image:" << path << std::endl;
		return -1;
	}
	cv::cvtColor(imageRGB, imageGray, cv::COLOR_RGB2GRAY);
	cv::imshow("ImageGray", imageGray);
	cv::waitKey(0);

	//去除噪声
	GaussianBlur(imageGray, imageGray, cv::Size(5, 5), 0, 0);//使用opencv自带高斯滤波预处理
	//获得背景
	cv::Mat imgPattern = calculateLightPattern(imageGray);
	//移除背景
	imageGray = removeLight(imageGray, imgPattern);
	cv::imshow("ImageGray", imageGray);
	cv::waitKey(0);
	//阈值化
	cv::Mat imageThr;
	cv::threshold(imageGray, imageThr, 50, 255, cv::THRESH_BINARY);
	cv::imshow("thr", imageThr);
	cv::waitKey(0);

	//通过连通组件算法分割
	cv::Mat labels, stats, centroids;
	int num_objects = connectedComponentsWithStats(imageThr, labels, stats, centroids);
	//检查检测出的数目数量
	if (num_objects < 2){
   
		std::cout << "No objects detected" << std::endl;
		return -1;
	}
	else{
   
		std::cout << "Number of objects detected: " << num_objects - 1 << std::endl;
	}
	//展示图像分割结果
	cv::Mat output = cv::Mat::zeros(imageThr.rows, imageThr.cols, CV_8UC3);
	cv::RNG randomNumGenerator(0xFFFFFFFF);
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值