重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

Opencv(C++)笔记--直方图比较、直方图反向投影-创新互联

目录

创新互联建站是一家集网站建设,广安企业网站建设,广安品牌网站建设,网站定制,广安网站建设报价,网络营销,网络优化,广安网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

1--直方图比较

1-1--四种常见比较方法

1-2--OpenCV API

1-3--代码实例

2--直方图反向投影

2-1--Opencv API

2-2--代码实例

2-3--代码分析

3--参考


1--直方图比较

  通过比较两幅图像的直方图,可以衡量两幅图像的相似和相关程度,一定程度上可以进行图像的匹配;

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 API

double 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 API

void 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元起,快前往官网查看详情吧


分享名称:Opencv(C++)笔记--直方图比较、直方图反向投影-创新互联
文章地址:http://cqcxhl.com/article/dcphjj.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP