在6说过一般是使用HSV的色调通道就行所以,所以我们可以直接写成一个函数,输入源图和roi返回反向直方图
static Mat HistBack(Mat src,Mat roi)
{
Mat srcHSV = new Mat();
Mat roiHSV = new Mat();
Cv2.CvtColor(src, srcHSV, ColorConversionCodes.BGR2HSV);//将图片转换成HSV空间
Cv2.CvtColor(roi, roiHSV, ColorConversionCodes.BGR2HSV);//将图片转换成HSV空间
int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 180.0F;//到180结束(不含,色调的范围0到180
int[] channels = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置
Mat[] rois = Cv2.Split(roiHSV);//将roi拆分
Mat[] rois0 = new Mat[] {rois[0] };//roi的第一个通道,也就是H,色调
Mat mask = new Mat();//掩码;
Cv2.Threshold(rois[1], mask, 65, 255, ThresholdTypes.BinaryInv);//过滤掉较低饱和度的像素
Mat[] hist = new Mat[] { new Mat() };//一个矩阵数组,用来接收直方图,记得初始化
Cv2.CalcHist(rois0, channels, mask, hist[0], 1, histsize, range);//把roi的色调通道转换成直方图
Mat[] srcs = new Mat[] { srcHSV };
Mat[] histBack = new Mat[] { new Mat() };//返回的反向直方图,一个通道就够
Cv2.CalcBackProject(srcs, channels, hist[0], histBack[0], range);//输出反向直方图
return histBack[0];
}
//试下
Mat src = new Mat(@"1.png", ImreadModes.AnyColor);
Rect rect = new Rect(520, 150, 80, 180);
Mat roi = new Mat(src, rect);
src.Rectangle(rect, Scalar.White);//在src上画框
Mat dst = new Mat(@"2.png", ImreadModes.AnyColor);
Cv2.MeanShift(HistBack(dst, roi), ref rect, new TermCriteria(CriteriaType.MaxIter, 10, 0.1));//框大小不会变化,其它一样
//Cv2.CamShift(HistBack(dst, roi), ref rect, new TermCriteria(CriteriaType.MaxIter, 10, 0.1));//框大小会变化
dst.Rectangle(rect, Scalar.White);//在dst上画框
Cv2.ImShow("dst", dst);
Cv2.ImShow("src", src);
Cv2.WaitKey();
emmmm
//需要 using OpenCvSharp.Extensions;
//pb5为winform的picturebox控件
//点击picturebox显示
Bitmap sion0;
bool sioni = false;
private void pB5_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
if (sioni)
{
g.DrawImage(sion0, 0, 0);
}
}
private void pB5_Click(object sender, EventArgs e)
{
Mat sion = new Mat("sion.png", ImreadModes.AnyColor);
double time = Environment.TickCount;//系统启功后到当前的时间
sion0 = sion.ToBitmap();//需要 using OpenCvSharp.Extensions;
UM_print((Environment.TickCount-time).ToString());//在输出串口打印出消耗的时间
sioni = true;
}
//直接显示
static Mat sion = new Mat("sion.png", ImreadModes.AnyColor);
static Bitmap sion0 = sion.ToBitmap();
private void pB5_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(sion0, 0, 0);
}
感谢@wyg2004 的提醒,已更新代码且满足性能需求,在当时困扰了好长一段时间。