扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
目录
创新互联建站是一家集网站建设,广安企业网站建设,广安品牌网站建设,网站定制,广安网站建设报价,网络营销,网络优化,广安网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。1--直方图比较
1-1--四种常见比较方法
1-2--OpenCV API
1-3--代码实例
2--直方图反向投影
2-1--Opencv API
2-2--代码实例
2-3--代码分析
3--参考
通过比较两幅图像的直方图,可以衡量两幅图像的相似和相关程度,一定程度上可以进行图像的匹配;
1-1--四种常见比较方法① 相关系数(cv::HISTCMP_CORREL):数值越大,相关度越高,大值为 1,最小值为 0;
② 卡方系数(cv::HISTCMP_CHISQR):数值越小,相关度越高,大值无上界,最小值为 0;
③ 相交系数(cv::HISTCMP_INTERSECT):数值越大,相关度越高,大值为 9.455319,最小值为 0;
④ 巴氏系数(cv::HISTCMP_BHATTACHARYYA):数值越小,相关度越高,大值为 1,最小值为 0;
具体数学公式参考直方图比较方法数学公式;
1-2--OpenCV APIdouble result12 = cv::compareHist(hist_src1, hist_src2, cv::HISTCMP_CORREL);
1-3--代码实例# include# include# includeint main(int argc, char** argv){
cv::Mat src1, src2;
src1 = cv::imread("C:/Users/Liujinfu/Desktop/opencv_bilibili/test1.jpg");
src2 = cv::imread("C:/Users/Liujinfu/Desktop/opencv_bilibili/test1_noise.jpg");
cv::Mat origin1, origin2;
src1.copyTo(origin1);
src2.copyTo(origin2);
if (src1.empty() || src2.empty()){
printf("could not load image..\n");
return -1;
}
cv::imshow("input1", src1);
cv::imshow("input2", src2);
cv::cvtColor(src1, src1, cv::COLOR_BGR2HSV);
cv::cvtColor(src2, src2, cv::COLOR_BGR2HSV);
int h_bins = 50, s_bins = 60;
int histSize[] = {h_bins, s_bins};
float h_ranges[] = {0, 180};
float s_ranges[] = {0, 256};
const float* ranges[] = {h_ranges, s_ranges};
int channels[] = {0, 1};
cv::MatND hist_src1, hist_src2;
cv::calcHist(&src1, 1, channels, cv::Mat(), hist_src1, 2, histSize, ranges, true, false);
cv::normalize(hist_src1, hist_src1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
cv::calcHist(&src2, 1, channels, cv::Mat(), hist_src2, 2, histSize, ranges, true, false);
cv::normalize(hist_src2, hist_src2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
double result11 = cv::compareHist(hist_src1, hist_src1, cv::HISTCMP_CORREL);
double result12 = cv::compareHist(hist_src1, hist_src2, cv::HISTCMP_CORREL);
cv::putText(origin1, std::to_string(result11), cv::Point(50, 50), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
cv::putText(origin2, std::to_string(result12), cv::Point(50, 50), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
cv::imshow("output1", origin1);
cv::imshow("output2", origin2);
cv::waitKey(0);
return 0;
}
2--直方图反向投影反向投影用于反映 输入图像的像素点去适应直方图模型像素分布 的方式,反向投影首先计算某一特征的直方图模型,然后使用该模型去寻找原图像中存在的特征。反向投影在某一位置的像素数值,表示原图像对应位置像素值在原图像中的总数目。
反向投影将图像特征反映到原图像上,对于图像中的物体特征识别和分割具有重要的作用。
2-1--Opencv APIvoid cv::calcBackProject(const cv::Mat *images, int nimages, const int *channels, cv::InputArray hist, cv::OutputArray backProject, const float **ranges, double scale = (1.0), bool uniform = true)
const cv::Mat *images:输入的图像或图像集,需要具有相同的尺寸和深度;
int nimages:输入图像的数目;
const int *channels:用于计算反向投影的通道列表,具体范围参考官方文档;
cv::InputArray hist:输入的直方图数据,即上面所说的计算得到的直方图模型;
cv::OutputArray backProject:目标反向投影输出图像,是一个单通道图像,与原图像有相同的尺寸和深度;
const float **ranges:直方图中每个维度bin的取值范围(将bin理解为横坐标,则ranges为纵坐标);
double scale = (1.0):可选输出反向投影的比例因子;
bool uniform = true:直方图是否均匀分布的标识符,默认值true;
2-2--代码实例# include# include# includevoid Hist_And_Backprojection(int bins, void* hue1){
float range[] = {0, 180};
const float *histRanges = {range}; // 直方图数据纵坐标的范围
cv::Mat h_hist; // 输出直方图数据
cv::Mat hue = *(cv::Mat*)(hue1); // 这里传入的是H色调,所以计算的是色调的直方图
cv::calcHist(&hue, 1, 0, cv::Mat(), h_hist, 1, &bins, &histRanges, true, false); // 计算直方图
cv::normalize(h_hist, h_hist, 0, 255, cv::NORM_MINMAX, -1, cv::Mat()); // 归一化到0~255
cv::Mat backPrjImage;
cv::calcBackProject(&hue, 1, 0, h_hist, backPrjImage, &histRanges, 1, true);
cv::imshow("output", backPrjImage);
// 直方图分布图
int hist_h = 600;
int hist_w = 600;
cv::Mat histImage(hist_w, hist_h, CV_8UC3, cv::Scalar(0, 0, 0));
int bin_w = cvRound((double)hist_w / bins);
for (size_t i = 0; i< bins; i++){
cv::rectangle(histImage, cv::Point(i*bin_w, hist_h),
cv::Point((i + 1) * bin_w, hist_h - cvRound(h_hist.at(i)*hist_h / 255.0)),
cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
}
cv::imshow("Histogram", histImage);
}
int main(int argc, char** argv){
int bins = 12; // 初始值
cv::Mat src1, hsv, hue;
src1 = cv::imread("C:/Users/Liujinfu/Desktop/opencv_bilibili/test1.jpg"); // 读取图片
if (src1.empty()){
printf("could not load image..\n");
return -1;
}
cv::imshow("input", src1);
cv::cvtColor(src1, hsv, cv::COLOR_BGR2HSV); // BRG ->HSV
hue.create(hsv.size(), hsv.depth()); // HSV H表示色调、S表示饱和度、V表示明暗度
int nchannels[] = {0, 0};
cv::mixChannels(&hsv, 1, &hue, 1, nchannels, 1); // 将一副图像的一个通道 复制到 另一幅图像的另一个通道
// 创建 Trackbar,回调函数为 Hist_And_Backprojection
cv::createTrackbar("Histogram Bins: ", "input", &bins, 180, Hist_And_Backprojection, &hue);
Hist_And_Backprojection(bins, &hue);
cv::waitKey(0);
return 0;
}
2-3--代码分析① 上述代码计算了 H(色调)的直方图,并基于 色调的直方图特征 计算原图像的反向投影,将色调的特征反映到原图像中;
② 上述代码调用cv::createTrackbar()的方式与常规方式不同,常规方式往往会使用全局变量,不传入参数,而上面的代码传入了两个参数,避免定义全局变量;
③ 上述代码使用了一个 cv::mixChannels() 函数,用于将一副图像的一个通道复制到另一幅图像的另一个通道上;以下展示 cv::mixChannels() 的具体用法:
//void cv::mixChannels(const cv::Mat *src, size_t nsrcs, cv::Mat *dst, size_t ndsts, const int *fromTo, size_t npairs)
cv::mixChannels(&hsv, 1, &hue, 1, nchannels, 1);
const cv::Mat *src:输入图片或图片集(即被复制的图片);
size_t nsrcs:输入图片的数目;
cv::Mat *dst:输出图片或图片集(即复制的目的图片)
size_t ndsts:输出图片的数目;
const int *fromTo:复制的索引,假设输入图片为三通道图像src1,其对应的通道为 src1[0] = 0, src1[1] = 1, src1[2] = 2; 输出图片为两个三通道图像dst1和dst2,则其对应的通道为 dst1[0] = 0, dst[1] = 1, dst1[2] = 2, dst2[0] = 3, dst2[1] = 4, dst2[2] = 5;当需要把src1的第一个通道复制到dst1的第二个通道,src1的第一个通道复制到dst2的第三个通道,则索引对需要设置为 {0, 1, 1, 5};
size_t npairs:索引对的数量,例如上面的复制索引 {0, 1, 1, 5},其索引对数目为 2;
3--参考C++ opencv之直方图反向投影(calcBackProject)
opencv —— mixChannels 通道复制
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流