创建项目 | 文件与显示 | 像素操作 | 图像彩色类型转换 | 模糊、平滑、去噪 | 锐化、边缘检测 | 二值化 | 形态学 | 位置变换 | 直方图 | 霍夫变换 | 图像优化 | 图像分割
完整示例项目
直方图是对图像灰度信息的一个统计结果,直方图的分布能够反映图像的某些特征,可用于图像匹配。
提取图像直方图的代码如下:
Mat src = new Mat(img_lenna, ImreadModes.Grayscale);
Mat hist = new Mat();
Cv2.CalcHist(new Mat[] { src }, new int[] { 0 }, new Mat(), hist, 1, new int[] { 256 }, new Rangef[] { new Rangef(0, 256) });
Cv2.Normalize(hist, hist);
Mat result = new Mat(new OpenCvSharp.Size(256, 500), MatType.CV_8UC1, new Scalar(255));
for (int i = 0; i < 256; i++)
{
float v = hist.Get(i);
int len = (int)(v * 500);
if (len != 0)
{
Cv2.Line(result, i, 499, i, 500 - len, new Scalar(0));
}
}
result.SaveImage(img_result);
需要注意的是,由于图像大小各异,一般我们会对直方图进行归一化处理,让每个灰度比例之和为1。
效果如下:
对于一些偏暗、偏亮的图片,其反映在直方图上的特征是灰度值偏向低强度或高强度,这样的图片看起来会不够清晰。如下图所示:
这种图片的一个处理方法是进行直方图均衡。实现代码如下:
Mat src = new Mat(img_dark, ImreadModes.Grayscale);
Mat result = new Mat();
Cv2.EqualizeHist(src, result);
result.SaveImage(img_result);
效果如下:
直方图比较是用于比较两张图像的相似性。比较的方法有很多,它们的结果不太一致:
完全匹配 | 一半匹配 | 完全不匹配 | |
Correl | 1 | 0.7 | -1 |
Chisqr | 0 | 0.67 | 2 |
Intersect | 1 | 0.5 | 0 |
Bhattacharyya | 0 | 0.55 | 1 |
EMD | 0 | 0.5 | 1 |
比较代码如下:
Mat p1 = new Mat(img_p1, ImreadModes.Grayscale);
Mat p2 = new Mat(img_p2, ImreadModes.Grayscale);
Mat hist1 = new Mat();
Cv2.CalcHist(new Mat[] { p1 }, new int[] { 0 }, new Mat(), hist1, 1, new int[] { 256 }, new Rangef[] { new Rangef(0, 256) });
Mat hist2 = new Mat();
Cv2.CalcHist(new Mat[] { p2 }, new int[] { 0 }, new Mat(), hist2, 1, new int[] { 256 }, new Rangef[] { new Rangef(0, 256) });
Cv2.Normalize(hist1, hist1);//比较前先进行归一化
Cv2.Normalize(hist2, hist2);
double near = Cv2.CompareHist(hist1, hist2, HistCompMethods.Bhattacharyya);
模板匹配实质也是直方图的比较,它是逐像素扫描,找出模板在原图中匹配度最高的区域。代码如下:
Mat src = new Mat(img_lenna, ImreadModes.Grayscale);
Mat templ = new Mat(img_template, ImreadModes.Grayscale);
Mat result = new Mat();
Cv2.MatchTemplate(src, templ, result, TemplateMatchModes.SqDiff);
Cv2.MinMaxLoc(result, out OpenCvSharp.Point minLoc, out OpenCvSharp.Point maxLoc);
minLoc、maxLoc是最优匹配区域和最差匹配区域所在的位置,根据匹配的方法使用不一样,采用最大值还是最小值会有些不一样。如果是SqDiff和SqDiffNormed,使用最小值,其他方法采用最大值。