基于反向投影的手部分割---简单版本

什么是反向投影?

  • 反向投影是一种记录给定图像中的像素点如何适应直方图模型像素分布的方式。
  • 所谓反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找图像中存在的该特征。

反向投影的原理

  • 假设你已经通过下图得到一个肤色直方图(Hue-Saturation), 旁边的直方图就是模型直方图 ( 代表手掌的皮肤色调).你可以通过掩码操作来抓取手掌所在区域的直方图。
  • 我们要做的就是使用 模型直方图 (代表手掌的皮肤色调) 来检测测试图像中的皮肤区域。以下是检测的步骤:
  1. 对测试图像中的每个像素 ( p(i,j) ),获取色调数据并找到该色调( ( h_{i,j}, s_{i,j} ) )在直方图中的bin的位置。
  2. 查询 模型直方图 中对应的bin - ( h_{i,j}, s_{i,j} ) - 并读取该bin的数值。
  3. 将此数值储存在新的图像中(BackProjection)。 你也可以先归一化 模型直方图 ,这样测试图像的输出就可以在屏幕显示了。
  4. 通过对测试图像中的每个像素采用以上步骤, 我们得到了下面的 BackProjection 结果图:
  5. 使用统计学的语言, BackProjection 中储存的数值代表了测试图像中该像素属于皮肤区域的 概率 。比如以上图为例, 亮起的区域是皮肤区域的概率更大(事实确实如此),而更暗的区域则表示更低的概率(注意手掌内部和边缘的阴影影响了检测的精度)。

相关实现代码

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/types_c.h"
#include <opencv2/core/core.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

Mat hsv, hue;
int bins = 25;

void Hist_and_Backproj(int, void*);

int main()
{
	// 读取图像
	Mat src = imread("palm.png", 1);
	if (!src.data)
	{
		printf("No data!--Exiting the program \n");
		return -1;
	}

	// 转换到 HSV 空间
	cvtColor(src, hsv, CV_BGR2HSV);

	// 分离 Hue 通道
	hue.create(hsv.size(), hsv.depth());
	int ch[] = { 0, 0 };
	mixChannels(&hsv, 1, &hue, 1, ch, 1);

	//创建Trackbar来输入bin的数目
	char* window_image = "Source Image";
	namedWindow(window_image, WINDOW_AUTOSIZE);
	createTrackbar("Hue bins: ", window_image, &bins, 180, Hist_and_Backproj);
	Hist_and_Backproj(0, 0);

	imshow(window_image, src);
	waitKey(0);

	return 0;
}

void Hist_and_Backproj(int, void*)
{
	MatND hist;
	int histSize = MAX(bins, 2);
	float hue_range[] = {0, 180};
	const float * ranges = { hue_range };

	//计算直方图并进行归一化处理
	calcHist(&hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false);
	normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat());

	//计算反向投影
	MatND backproj;
	calcBackProject(&hue, 1, 0, hist, backproj, &ranges, 1, true);

	//显示反向投影
	imshow("BackProj", backproj);

	//显示直方图
	int w = 400; int h = 400;
	int bin_w = cvRound((double)w / histSize);
	Mat histImg = Mat::zeros(w, h, CV_8UC3);

	for (int i = 0; i < bins; i++)
	{
		rectangle(histImg, Point(i*bin_w, h), Point((i + 1)*bin_w, h - cvRound(hist.at<float>(i)*h / 255.0)), Scalar(0, 0, 255), -1);
	}
    
	imshow("Histogram", histImg);
}

关键代码讲解

  • 申明图像矩阵,初始化bin数目
Mat src; Mat hsv; Mat hue;
int bins = 25;
  • 读取输入图像并转换到HSV格式
src = imread( argv[1], 1 );
cvtColor( src, hsv, CV_BGR2HSV );
  • 使用Hue通道来创建1维直方图
hue.create( hsv.size(), hsv.depth() );
int ch[] = { 0, 0 };
mixChannels( &hsv, 1, &hue, 1, ch, 1 );
  • 创建Trackbar方便用户输入bin数目。 Trackbar的任何变动将会调用函数 Hist_and_Backproj 。
char* window_image = "Source image";
namedWindow( window_image, CV_WINDOW_AUTOSIZE );
createTrackbar("* Hue  bins: ", window_image, &bins, 180, Hist_and_Backproj );
Hist_and_Backproj(0, 0);
  • 显示并等待用户突出程序
imshow( window_image, src );
waitKey(0);
return 0;
  • Hist_and_Backproj 函数: 初始化函数 calcHist 需要的实参, bin数目来自于 Trackbar
void Hist_and_Backproj(int, void* )
{
  MatND hist;
  int histSize = MAX( bins, 2 );
  float hue_range[] = { 0, 180 };
  const float* ranges = { hue_range };
}
  • 计算直方图并归一化到范围 [0,255]
calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );
normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );
MatND backproj;
calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );
  • 显示 backproj
imshow( "BackProj", backproj );
  • 显示1维 Hue 直方图
int w = 400; int h = 400;
int bin_w = cvRound( (double) w / histSize );
Mat histImg = Mat::zeros( w, h, CV_8UC3 );

for( int i = 0; i < bins; i ++ )
   { rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ), Scalar( 0, 0, 255 ), -1 ); }

imshow( "Histogram", histImg );

函数详解

  1. &hsv: 一系列输入图像的数组, 被拷贝的通道的来源
  2. 1: 输入数组中图像的数目
  3. &hue: 一系列目的图像的数组, 储存拷贝的通道
  4. 1: 目的数组中图像的数目
  5. ch[] = {0,0}: 通道索引对的数组,指示如何将输入图像的某一通道拷贝到目的图像的某一通道。在这里,&hsv图像的Hue(0) 通道被拷贝到&hue图像(单通道)的0 通道。
  6. 1: 通道索引对的数目

  1. 函数原型:void normalize(InputArray src,OutputArraydst, double alpha = 1, double beta = 0, intnorm_type = NORM_L2, int dtype = -1, InputArray mask = noArray() )
  2. 参数详解:

    src:       输入数组   

    dst:       输出数组,支持原地运算

    alpha:   range normalization模式的最小值

    beta:     range normalization模式的最大值,不用于norm normalization(范数归一化)模式。

    normType:归一化的类型,可以有以下的取值:

        NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化,一般较常用。

        NORM_INF:此类型的定义没有查到,根据OpenCV 1的对应项,可能是归一化数组的C-范数(绝对值的最大值)

        NORM_L1 :  归一化数组的L1-范数(绝对值的和)

        NORM_L2: 归一化数组的(欧几里德)L2-范数

    dtype :     dtype为负数时,输出数组的type与输入数组的type相同;否则,输出数组与输入数组只是通道数相同,而tpye=CV_MAT_DEPTH(dtype).

    mask:       操作掩膜,用于指示函数是否仅仅对指定的元素进行操作。

  1. 函数原型:C++: void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
  2. 参数详解:

    onst Mat* images:输入图像

     int nimages:输入图像的个数

    const int* channels:需要统计直方图的第几通道

    InputArray mask:掩膜,,计算掩膜内的直方图  ...Mat()

    OutputArray hist:输出的直方图数组

    int dims:需要统计直方图通道的个数

    const int* histSize:指的是直方图分成多少个区间,就是 bin的个数

    const float** ranges: 统计像素值得区间

    bool uniform=true::是否对得到的直方图数组进行归一化处理

    bool accumulate=false:在多个图像时,是否累计计算像素值得个数

实验效果

实验代码下载

https://download.csdn.net/download/lykymy/11295315

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习是一种人工智能(AI)的子领域,致力于研究如何利用数据和算法让计算机系统具备学习能力,从而能够自动地完成特定任务或者改进自身性能。机器学习的核心思想是让计算机系统通过学习数据中的模式和规律来实现目标,而不需要显式地编程。 机器学习应用非常广泛,包括但不限于以下领域: 图像识别和计算机视觉: 机器学习在图像识别、目标检测、人脸识别、图像分割等方面有着广泛的应用。例如,通过深度学习技术,可以训练神经网络来识别图像中的对象、人脸或者场景,用于智能监控、自动驾驶、医学影像分析等领域。 自然语言处理: 机器学习在自然语言处理领域有着重要的应用,包括文本分类、情感分析、机器翻译、语音识别等。例如,通过深度学习模型,可以训练神经网络来理解和生成自然语言,用于智能客服、智能助手、机器翻译等场景。 推荐系统: 推荐系统利用机器学习算法分析用户的行为和偏好,为用户推荐个性化的产品或服务。例如,电商网站可以利用机器学习算法分析用户的购买历史和浏览行为,向用户推荐感兴趣的商品。 预测和预测分析: 机器学习可以用于预测未来事件的发生概率或者趋势。例如,金融领域可以利用机器学习算法进行股票价格预测、信用评分、欺诈检测等。 医疗诊断和生物信息学: 机器学习在医疗诊断、药物研发、基因组学等领域有着重要的应用。例如,可以利用机器学习算法分析医学影像数据进行疾病诊断,或者利用机器学习算法分析基因数据进行疾病风险预测。 智能交通和物联网: 机器学习可以应用于智能交通系统、智能城市管理和物联网等领域。例如,可以利用机器学习算法分析交通数据优化交通流量,或者利用机器学习算法分析传感器数据监测设备状态。 以上仅是机器学习应用的一部分,随着机器学习技术的不断发展和应用场景的不断拓展,机器学习在各个领域都有着重要的应用价值,并且正在改变我们的生活和工作方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值