首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

图像识别10 图像直方图2

越往下写 ,越感觉自己的基础越薄弱。

这是图像直方图程序 笔记:

本身就是什么都不懂的小白,装什么,服了自己。

好了,开始,看程序时,突然有个问题--1.为什么有的函数有cv::,有时又不带?懵逼

查了网上答案,好像理解了。

OpenCV所有类及函数都放在CV命名空间里,所以使用这些类或者函数时需要cv::

如此例:

也可以使用using namespace cv;指令,之后使用这些类或者函数就可以省略cv::

如此例:

2.system("color 1f");是什么意思啊 ?

c语言中的 system 就是调用dos命令。

color 1f 是用来设置Dos窗口颜色的; 前面的 1 设置窗口背景颜色,f 设置窗口字体颜色(前景颜色);这样的颜色值只有4位,依次是: 高亮,R, G, B 来分的;因此 1 是蓝色,F 是高亮白色。背景蓝色,字体高亮白色;

指定控制台输出的颜色属性

颜色属性由两个十六进制数字指定 -- 第一个为背景,第二个则为

前景。每个数字可以为以下任何值之一:

0 = 黑色 8 = 灰色

1 = 蓝色 9 = 淡蓝色

2 = 绿色 A = 淡绿色

3 = 湖蓝色 B = 淡浅绿色

4 = 红色 C = 淡红色

5 = 紫色 D = 淡紫色

6 = 黄色 E = 淡黄色

7 = 白色 F = 亮白色

3.mat和matnd的区别:

简单的说,Mat特指2维矩阵,MatND是多维矩阵(>=3维);

Mat对象提供了size()、channels()和depth()等方法分别获得图像的大小、通道数和数值类型。上面的例子中,图像img的宽为512个像素,高为393个像素,有3个通道(channels),即图像中的每个像素的颜色用三个数值表示。每个通道的数值类型(depth)的编号为0,0表示无符号8bit整数。

MatND对象使用size和step属性保存每个轴的长度和每个轴的字节偏移量,它们和NumPy数组的shape和strides属性类似。但是这两个属性都是长度固定为32的整数数组。

所以今天给大家一个解释更清楚的程序,并且能显示值

#include

#include

#include

#include

int main()

{

//首先肯定是读取图片,转换为灰度图并且在一个窗口上面显示

cv::Mat sourcePic = cv::imread("D:\\abc\\1.jpg", cv::IMREAD_GRAYSCALE);

cv::imshow("Source Picture", sourcePic);

//定义函数需要的一些变量

//图片数量nimages

int nimages = 1;

//通道数量,我们总是习惯用数组来表示,后面会讲原因

int channels[1] = { 0 };

//输出直方图

cv::Mat outputHist;

//维数

int dims = 1;

//存放每个维度直方图尺寸(bin数量)的数组histSize

int histSize[1] = { 256 };

//每一维数值的取值范围ranges

float hranges[2] = { 0, 255 };

//值范围的指针

const float *ranges[1] = { hranges };

//是否均匀

bool uni = true;

//是否累积

bool accum = false;

//计算图像的直方图

cv::calcHist(&sourcePic, nimages, channels, cv::Mat(), outputHist, dims, histSize, ranges, uni, accum);

//遍历每个箱子(bin)检验,这里的是在控制台输出的。

for (int i = 0; i

std::cout (i)

//画出直方图

int scale = 1;

//直方图的图片

cv::Mat histPic(histSize[0] * scale, histSize[0], CV_8U, cv::Scalar(255)); \

//找到最大值和最小值

double maxValue = 0;

double minValue = 0;

cv::minMaxLoc(outputHist, &minValue, &maxValue, NULL, NULL);

//测试

std::cout

std::cout

//纵坐标缩放比例

double rate = (histSize[0] / maxValue)*0.9;

for (int i = 0; i

{

//得到每个i和箱子的值

float value = outputHist.at(i);

//画直线

cv::line(histPic, cv::Point(i*scale, histSize[0]), cv::Point(i*scale, histSize[0] - value * rate), cv::Scalar(0));

}

cv::imshow("histgram", histPic);

cv::waitKey(0);

}

运行结果:

这样你就能看到每个占了多少。

根据峰值,再取阈值,再取二值化就可分割出前景和背景,甚至提取出你想要的目标。

再说下彩色图片,自然有了三个特征,那么维度便变为了3,依然是以上面那副图片作为例子,计算和画出三维的GBG直方图。

程序:

#include

#include

#include

#include

int main()

{

//首先肯定是彩色形式读取图片

cv::Mat sourcePic = cv::imread("D:\\abc\\1.jpg");

cv::imshow("Source Picture", sourcePic);

//定义函数需要的一些变量

//图片数量nimages

int nimages = 1;

//通道数量,我们总是习惯用数组来表示,后面会讲原因

int channels[3] = { 0,1,2 };

//输出直方图

cv::Mat outputHist_red, outputHist_green, outputHist_blue;

//维数

int dims = 1;

//存放每个维度直方图尺寸(bin数量)的数组histSize

int histSize[3] = { 256,256,256 };

//每一维数值的取值范围ranges

float hranges[2] = { 0, 255 };

//值范围的指针

const float *ranges[3] = { hranges,hranges,hranges };

//是否均匀

bool uni = true;

//是否累积

bool accum = false;

//计算图像的直方图(红色通道部分)

cv::calcHist(&sourcePic, nimages, &channels[0], cv::Mat(), outputHist_red, dims, &histSize[0], &ranges[0], uni, accum);

//计算图像的直方图(绿色通道部分)

cv::calcHist(&sourcePic, nimages, &channels[1], cv::Mat(), outputHist_green, dims, &histSize[1], &ranges[1], uni, accum);

//计算图像的直方图(蓝色通道部分)

cv::calcHist(&sourcePic, nimages, &channels[2], cv::Mat(), outputHist_blue, dims, &histSize[2], &ranges[2], uni, accum);

//遍历每个箱子(bin)检验,这里的是在控制台输出的。

//for (int i = 0; i

//std::cout (i)

//画出直方图

int scale = 1;

//直方图的图片,因为尺寸是一样大的,所以就以histSize[0]来表示全部了.

cv::Mat histPic(histSize[0], histSize[0] * scale * 3, CV_8UC3, cv::Scalar(0, 0, 0));

//找到最大值和最小值,索引从0到2分别是红,绿,蓝

double maxValue[3] = { 0, 0, 0 };

double minValue[3] = { 0, 0, 0 };

cv::minMaxLoc(outputHist_red, &minValue[0], &maxValue[0], NULL, NULL);

cv::minMaxLoc(outputHist_green, &minValue[1], &maxValue[1], NULL, NULL);

cv::minMaxLoc(outputHist_blue, &minValue[2], &maxValue[2], NULL, NULL);

//测试

std::cout

std::cout

//纵坐标缩放比例

double rate_red = (histSize[0] / maxValue[0])*0.9;

double rate_green = (histSize[0] / maxValue[1])*0.9;

double rate_blue = (histSize[0] / maxValue[2])*0.9;

for (int i = 0; i

{

float value_red = outputHist_red.at(i);

float value_green = outputHist_green.at(i);

float value_blue = outputHist_blue.at(i);

//分别画出直线

cv::line(histPic, cv::Point(i*scale, histSize[0]), cv::Point(i*scale, histSize[0] - value_red * rate_red), cv::Scalar(0, 0, 255));

cv::line(histPic, cv::Point((i + 256)*scale, histSize[0]), cv::Point((i + 256)*scale, histSize[0] - value_green * rate_green), cv::Scalar(0, 255, 0));

cv::line(histPic, cv::Point((i + 512)*scale, histSize[0]), cv::Point((i + 512)*scale, histSize[0] - value_blue * rate_blue), cv::Scalar(255, 0, 0));

}

cv::imshow("histgram", histPic);

cv::waitKey(0);

}

运行结果:

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190111G16BY500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券