交流做病理切片的网站,小红书kol推广,程序员培训机构出来找工作好找吗,做网站采集返回:OpenCV系列文章目录#xff08;持续更新中......#xff09;
上一篇#xff1a;OpenCV直方图比较(57)
下一篇#xff1a;OpenCV如何模板匹配(59) 目标
在本教程中#xff0c;您将学习#xff1a;
什么是背投以及它为什么有用如何使用 OpenCV 函数 cv::calcBackP… 返回:OpenCV系列文章目录持续更新中......
上一篇OpenCV直方图比较(57)
下一篇OpenCV如何模板匹配(59) 目标
在本教程中您将学习
什么是背投以及它为什么有用如何使用 OpenCV 函数 cv::calcBackProject 计算背投如何使用 OpenCV 函数 cv::mixChannels 混合图像的不同通道
cv::mixChannels 和 cv::calcBackProject 都是 OpenCV 库中常用的图像处理函数主要应用于通道处理、直方图反向投影等操作。
cv::mixChannels 是一个通道处理函数它可以在不同的图像通道之间进行拷贝、转换和简单操作等处理。该函数的主要思路是定义一个通道映射表来指定源和目标图像之间的通道拷贝关系并在映射表中指定每个通道的源图像和目标图像之间的通道位置和通道数。通过 mixChannels 函数我们可以实现在不同通道间进行像素值的传递和处理等图像操作。
cv::calcBackProject 是一个直方图反向投影函数它可以用于将某个模型区域的像素在目标图像中得到的直方图投影回去以便进行目标检测和跟踪等操作。该函数主要思路是首先使用 calcHist 函数计算模型区域的直方图然后在目标图像中使用 calcBackProject 函数计算每个像素点在该直方图上的投影分布并生成反向投影图像。利用反向投影图像我们可以定位目标区域并识别出图像中存在的目标区域。
因此cv::mixChannels 和 cv::calcBackProject 函数通常会一起使用。通过 mixChannels 函数进行通道拷贝和转换处理然后利用 calcBackProject 函数生成反向投影图像可以实现更加精确的目标区域定位和识别。这些函数广泛用于计算机视觉和图像处理等领域中的特定应用和算法中。
理论
什么是背投
背投是一种记录给定图像的像素与直方图模型中像素分布的拟合程度的方法。为简化起见对于“背投”您可以计算要素的直方图模型然后使用它在影像中查找此要素。应用示例如果您有肉色直方图例如色相饱和度直方图则可以使用它来查找图像中的肉色区域
它是如何工作的
我们通过使用皮肤示例来解释这一点假设您已经根据下图获得了皮肤直方图色相饱和度。此外直方图将是我们的模型直方图我们知道它代表了肤色的样本。您应用了一些蒙版来仅捕获皮肤区域的直方图 现在让我们想象一下你得到另一个手部图像测试图像如下所示及其各自的直方图 我们想要做的是使用我们的模型直方图我们知道它代表皮肤色调来检测测试图像中的皮肤区域。步骤如下 在我们的测试图像的每个像素即pij中收集数据并找到该像素的相应箱位置即 h{ij}, s{ij} 。在相应的 bin 中查找模型直方图 h{ij} s{ij} - 并读取 bin 值。将此图柱值存储在新图像 BackProjection 中。此外您可以考虑先对模型直方图进行归一化以便您可以看到测试图像的输出。应用上述步骤我们得到以下测试图像的 BackProjection 图像 在统计方面存储在 BackProjection 中的值表示测试图像中的像素属于皮肤区域的概率基于我们使用的模型直方图。例如在我们的测试图像中较亮的区域更有可能是皮肤区域实际上确实如此而较暗区域的可能性较小请注意这些“黑暗”区域属于带有一些阴影的表面这反过来又会影响检测。
C代码
这个程序是做什么的 加载图像将原始格式转换为 HSV 格式并仅分离用于直方图的 Hue 通道使用 OpenCV 函数 cv::mixChannels )让用户输入用于计算直方图的箱数。计算直方图并在条柱更改时更新它和同一图像的背投。在窗口中显示背投和直方图。 可下载代码 单击此处获取基本版本在本教程中解释。对于稍微花哨的东西使用 H-S 直方图和 floodFill 为皮肤区域定义蒙版您可以查看改进的演示...或者您可以随时查看示例中的经典 CamshiftDemo。代码一览 #include opencv2/imgproc.hpp
#include opencv2/imgcodecs.hpp
#include opencv2/highgui.hpp#include iostreamusing namespace cv;
using namespace std;Mat hue;
int bins 25;void Hist_and_Backproj(int, void* );int main( int argc, char* argv[] )
{CommandLineParser parser( argc, argv, {input |Back_Projection_Theory0.jpg| input image} );samples::addSamplesDataSearchSubDirectory(doc/tutorials/imgproc/histograms/back_projection/images);Mat src imread(samples::findFile(parser.getString( input )) );if( src.empty() ){cout Could not open or find the image!\n endl;cout Usage: argv[0] Input image endl;return -1;}Mat hsv;cvtColor( src, hsv, COLOR_BGR2HSV );hue.create(hsv.size(), hsv.depth());int ch[] { 0, 0 };mixChannels( hsv, 1, hue, 1, ch, 1 );const char* window_image Source image;namedWindow( window_image );createTrackbar(* Hue bins: , window_image, bins, 180, Hist_and_Backproj );Hist_and_Backproj(0, 0);imshow( window_image, src );// Wait until user exits the programwaitKey();return 0;
}void Hist_and_Backproj(int, void* )
{int histSize MAX( bins, 2 );float hue_range[] { 0, 180 };const float* ranges[] { hue_range };Mat hist;calcHist( hue, 1, 0, Mat(), hist, 1, histSize, ranges, true, false );normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );Mat backproj;calcBackProject( hue, 1, 0, hist, backproj, ranges, 1, true );imshow( BackProj, backproj );int w 400, h 400;int bin_w cvRound( (double) w / histSize );Mat histImg Mat::zeros( h, w, CV_8UC3 );for (int i 0; i bins; i){rectangle( histImg, Point( i*bin_w, h ), Point( (i1)*bin_w, h - cvRound( hist.atfloat(i)*h/255.0 ) ),Scalar( 0, 0, 255 ), FILLED );}imshow( Histogram, histImg );
}
解释
读取输入图像
CommandLineParser parser( argc, argv, {input |Back_Projection_Theory0.jpg| input image} );samples::addSamplesDataSearchSubDirectory(doc/tutorials/imgproc/histograms/back_projection/images);Mat src imread(samples::findFile(parser.getString( input )) );if( src.empty() ){cout Could not open or find the image!\n endl;cout Usage: argv[0] Input image endl;return -1;}
将其转换为 HSV 格式 Mat hsv;cvtColor( src, hsv, COLOR_BGR2HSV );
在本教程中我们将仅将 Hue 值用于我们的一维直方图如果您想使用更标准的 H-S 直方图请查看上面链接中的更高级代码这会产生更好的结果 hue.create(hsv.size(), hsv.depth());int ch[] { 0, 0 };mixChannels( hsv, 1, hue, 1, ch, 1 );
如您所见我们使用函数 cv::mixChannels 仅从 hsv 图像中获取通道 0色相。它获取以下参数 HSV将从中复制通道的源数组1源数组的数量色相C复制通道的目标数组1目标数组的数量ch[] {0,0}指示如何复制通道的索引对数组。在本例中将 hsv 的 Hue0 通道复制到 hue 的 0 通道1 通道1索引对数 为用户创建用于输入图格值的跟踪栏。对 Trackbar 的任何更改都意味着对 Hist_and_Backproj回调函数的调用。 const char* window_image Source image;namedWindow( window_image );createTrackbar(* Hue bins: , window_image, bins, 180, Hist_and_Backproj );Hist_and_Backproj(0, 0);
显示图像并等待用户退出程序 imshow( window_image, src );// Wait until user exits the programwaitKey();
Hist_and_Backproj功能初始化 cv::calcHist 所需的参数。条柱数量来自 Trackbar int histSize MAX( bins, 2 );float hue_range[] { 0, 180 };const float* ranges[] { hue_range };
计算直方图并将其归一化为范围 [0,255] Mat hist;calcHist( hue, 1, 0, Mat(), hist, 1, histSize, ranges, true, false );normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() ); 通过调用函数 cv::calcBackProject 获取同一图像的反向投影 Mat backproj;calcBackProject( hue, 1, 0, hist, backproj, ranges, 1, true );
所有参数都是已知的与用于计算直方图的参数相同只是我们添加了 BackProj 矩阵它将存储源图像 hue 的反向投影 显示 backproj imshow( BackProj, backproj );
绘制图像的一维色相直方图 int w 400, h 400;int bin_w cvRound( (double) w / histSize );Mat histImg Mat::zeros( h, w, CV_8UC3 );for (int i 0; i bins; i){rectangle( histImg, Point( i*bin_w, h ), Point( (i1)*bin_w, h - cvRound( hist.atfloat(i)*h/255.0 ) ),Scalar( 0, 0, 255 ), FILLED );}imshow( Histogram, histImg );
结果
以下是使用示例图像的输出你猜怎么着另一只手。您可以使用 bin 值您将观察它如何影响结果 参考文献
1、《Back Projection》-----Ana Huamán