// computes the joint dense histogram for a set of images.
// 计算一组图像的联合密集直方图。
// 参数:
// images://输入图像
//
// channels://通道,输入图像是哪个通道
//
// mask://掩码一般直接用 Mat mask = new Mat ();也就是不做掩码
//
// hist://输出也是一个mat
//
// dims://维数
//
// histSize://箱子数量,多少不同像素值就有多少个箱子,例如灰度图像就是256个
// 0号箱子装的就是值位0的像素数量
// ranges://像素值范围
//
// uniform:
//
// accumulate:
public static void CalcHist(Mat[] images, int[] channels, InputArray mask, OutputArray hist, int dims, int[] histSize, float[][] ranges, bool uniform = true, bool accumulate = false);
public static void CalcHist(Mat[] images, int[] channels, InputArray mask, OutputArray hist, int dims, int[] histSize, Rangef[] ranges, bool uniform = true, bool accumulate = false);
//直方图也是c++有写差别的地方,从形参上来看就比c++的少了个图片数量
Mat panda = new Mat(@"滚滚.png", ImreadModes.GrayScale);//读取为灰度图
Mat[] mats = new Mat[] { panda};//一张图片,初始化为panda
Mat hist = new Mat();//用来接收直方图
int[] channels = new int[] { 0};//一个通道,初始化为通道0
int[] histsize = new int[] { 256};//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,值范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats, channels, mask, hist, 1, histsize, range);//计算灰度图,dim为1 1维
Console.WriteLine(hist.Rows + "行" + hist.Cols + "列");//把输出的行列打印出来
Cv2.ImShow("处理后", panda);
Cv2.WaitKey();
/在前面的基础上
//Console.WritleLine的后面加上
for (int i = 0; i < 256; i++)//画直方图
{
int len = (int)((hist.Get(i) / 10000) * panda.Rows);//单个箱子的长度,
// 10000) * panda.Rows)的作用只是让他变短,别超出了
Cv2.Line(panda, i, 0, i, len, Scalar.Black, 2);//把线画出来
}
Mat panda = new Mat(@"滚滚.png", ImreadModes.AnyColor);//读取为彩图
Mat[] mats = new Mat[] { panda};//一张图片,初始化为panda
//Mat hist = new Mat();//用来接收直方图
int[] channels = new int[] { 0,1,2};//三个通道,初始化为通道0
int[] histsize = new int[] { 256,256,256};//三个通道,初始化为256箱子
Rangef[] range = new Rangef[3];//三个通道,范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
range[1] = range[0];//通道2和通道1一样
range[2] = range[0];//通道3和通道1一样
Mat mask = new Mat();//不做掩码
SparseMat hist0 = new SparseMat(histsize, MatType.CV_32F);
Cv2.CalcHist(mats, channels, mask,hist0 ,3, histsize, range);//dim为3 3维
Console.WriteLine(hist.Rows + "行" + hist.Cols + "列");
//这是照着c++写的,然而它并不能运行,这是因为opencvsharp没有针对稀疏矩阵的重载
//具体原因不明
Mat panda = new Mat(@"滚滚.png", ImreadModes.AnyColor);//读取为彩图
Mat[] mats =Cv2.Split(panda);//一张图片,将panda拆分成3个图片装进mat
Mat[] mats0 = new Mat[] { mats[0]};//panda的第一个通道,也就是B
Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
Mat[] hist = new Mat[] {new Mat(),new Mat (),new Mat ()};//一个矩阵数组,用来接收直方图,记得全部初始化
int[] channels = new int[] { 0};//一个通道,初始化为通道0,这些东西可以共用设置一个就行
int[] histsize = new int[] { 256};//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats0, channels, mask, hist[0],1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats1, channels, mask, hist[1], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats2, channels, mask, hist[2], 1, histsize, range);//对被拆分的图片单独进行计算
for (int i = 0; i < 3; i++)
{
Console.WriteLine(hist[i].Rows + "行" + hist[i].Cols + "列");
}
Cv2.ImShow("处理后", panda);
Cv2.WaitKey();
运行结果 //在Cv2.ImShow("处理后", panda);前面加上
Scalar[] color = new Scalar[] { Scalar.Blue, Scalar.Green, Scalar.Red };//BGR线条颜色
for (int i = 0; i < 256; i++)//画直方图
{
for (int j = 0; j < 3; j++)
{ int len = (int)((hist[j].Get(i) / 10000) * panda.Rows);
Cv2.Line(panda,i,0,i,len, color[j], 2);
}
}
// 摘要:
// computes the joint dense histogram for a set of images.
//计算一组图像的联合稠密直方图。
// 参数:
// images:
//图像
// channels:
//通道
// hist:
//直方图
// backProject:
//反向投影直方图
// ranges:
//范围
// uniform:
public static void CalcBackProject(Mat[] images, int[] channels, InputArray hist, OutputArray backProject, Rangef[] ranges, bool uniform = true);
Mat panda = new Mat(@"滚滚.png", ImreadModes.AnyColor);//读取为彩图
Mat src = new Mat();
panda.CopyTo(src);//作为对比
Rect rect = new Rect(30, 250, 50, 50);//roi的区域
Mat roi = new Mat(panda, rect);//定义roi
Cv2.Rectangle(src, rect, Scalar.White);
Cv2.ImShow("roi", src);
Mat[] mats = Cv2.Split(roi);//一张图片,将panda拆分成3个图片装进mat
Mat[] mats0 = new Mat[] { mats[0] };//panda的第一个通道,也就是B
Mat[] mats1 = new Mat[] { mats[1] };//panda的第二个通道,也就是G
Mat[] mats2 = new Mat[] { mats[2] };//panda的第三个通道,也就是R
Mat[] hist = new Mat[] { new Mat(), new Mat(), new Mat() };//一个矩阵数组,用来接收直方图,记得全部初始化
int[] channels = new int[] { 0 };//一个通道,初始化为通道0,这些东西可以共用设置一个就行
int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats0, channels, mask, hist[0], 1, histsize, range);//对被拆分的图片单独进行计算
Cv2.CalcHist(mats1, channels, mask, hist[1], 1, histsize, range);
Cv2.CalcHist(mats2, channels, mask, hist[2], 1, histsize, range);
Mat[] pandas = new Mat[] { panda };
Mat[] histBack = new Mat[] { new Mat(), new Mat(), new Mat() };//用来接收转换的反向直方图
Cv2.CalcBackProject(pandas, channels, hist[0], histBack[0], range);
Cv2.CalcBackProject(pandas, channels, hist[1], histBack[1], range);
Cv2.CalcBackProject(pandas, channels, hist[2], histBack[2], range);
Cv2.Merge(histBack, panda);
Cv2.ImShow("处理后", panda);
Cv2.WaitKey();
可以看出越黑的地方概率越低,不过这样还是不太适合人看。实际上更多的时候使用一个通道就够,为了突出被寻找物体的特征,一般将图片转换成HSV空间,仅使用色调的通道,
并且过滤掉较低饱和度的像素,因为饱和度在较低时色调会变得不稳定
Mat panda = new Mat(@"sky.png", ImreadModes.AnyColor);//读取为彩图
Mat src = new Mat();
panda.CopyTo(src);//作为对比
Mat[] hist = new Mat[] {new Mat()};//一个矩阵数组,用来接收直方图,记得全部初始化
int[] channels = new int[] { 0};//一个通道,初始化为通道0,这些东西可以共用设置一个就行
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
Cv2.CvtColor(panda, panda, ColorConversionCodes.BGR2HSV);//将图片转换成HSV空间
Rect rect = new Rect(30,550,50, 50);//roi的区域
Mat roi = new Mat(panda,rect);//定义roi
Cv2.Rectangle(src, rect, Scalar.White);
Cv2.ImShow("roi", src);
Mat[] mats = Cv2.Split(roi);//将图片拆分
Mat mask =new Mat();//掩码
Cv2.Threshold(mats[1], mask,50, 255, ThresholdTypes.Binary);//过滤掉较低饱和度的像素
Mat[] mats0 = new Mat[] { mats[0] };//图片的第一个通道,也就是H,色调
Cv2.CalcHist(mats0, channels, mask, hist[0],1, histsize, range);//转换成直方图
Mat[] pandas = new Mat[] { panda };
Mat[] histBack = new Mat[] { new Mat()};//一个通道就够
Cv2.CalcBackProject(pandas, channels, hist[0], histBack[0], range);//转换成反向直方图
Cv2.Threshold(histBack[0], histBack[0], 120, 255, ThresholdTypes.Binary);//二值化,更容易看出来,去不去无所谓
Cv2.ImShow("处理后", histBack[0]);
Cv2.WaitKey(););
运行结果roi是最下角的那朵花