最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

利用C++和OpenCV庫計(jì)算圖像顏色直方圖并比較相似度

 更新時(shí)間:2025年06月05日 10:23:02   作者:whoarethenext  
本文介紹如何利用 C++ 和 OpenCV 庫計(jì)算圖像的顏色直方圖,并使用不同的方法比較兩張圖片的相似度,直方圖比較是圖像檢索、目標(biāo)識別等領(lǐng)域中一種簡單而有效的技術(shù),感興趣的小伙伴跟著小編一起來看看吧

簡介

圖像直方圖是圖像中像素強(qiáng)度分布的圖形表示。對于彩色 圖像,我們通常會為每個(gè)顏色通道(例如 BGR 或 HSV)計(jì)算直方圖。通過比較兩張圖片的直方圖,我們可以獲得它們在顏色分布上的相似程度。OpenCV 提供了 cv::calcHist 函數(shù)用于計(jì)算直方圖,以及 cv::compareHist 函數(shù)用于比較兩個(gè)直方圖。

先決條件

  • C++ 編譯器: 如 G++ (MinGW for Windows), Clang, MSVC。
  • OpenCV 庫: 需要正確安裝并配置好編譯環(huán)境 (版本 3.x 或 4.x)。
  • 兩張待比較的圖像: 準(zhǔn)備好兩張圖片文件(例如 image1.jpg 和 image2.jpg)。

核心步驟

  1. 加載圖像: 使用 cv::imread 讀取兩張待比較的圖像。
  2. 色彩空間轉(zhuǎn)換 (可選但推薦): 將圖像從 BGR 轉(zhuǎn)換到 HSV 色彩空間。HSV 對光照變化的魯棒性通常比 BGR 好,尤其是 H (Hue) 和 S (Saturation) 通道。
  3. 計(jì)算直方圖:
    • 定義直方圖參數(shù)(如通道、bins 數(shù)量、取值范圍)。
    • 使用 cv::calcHist 為每張圖像計(jì)算 H-S 二維直方圖或單個(gè)通道的一維直方圖。
  4. 歸一化直方圖 (可選但推薦): 為了消除圖像尺寸差異帶來的影響,通常會對直方圖進(jìn)行歸一化,使其和為1??梢允褂?nbsp;cv::normalize。
  5. 比較直方圖: 使用 cv::compareHist 函數(shù),選擇一種比較方法(如相關(guān)性、卡方、交集、巴氏距離)來計(jì)算兩個(gè)直方圖之間的相似度/差異度。
  6. 輸出結(jié)果: 顯示比較得分。

代碼實(shí)現(xiàn)

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

// 函數(shù):計(jì)算并歸一化圖像的 H-S 直方圖
cv::Mat calculateHSNormalizedHistogram(const cv::Mat& image) {
    cv::Mat hsvImage;
    cv::cvtColor(image, hsvImage, cv::COLOR_BGR2HSV);

    // H-S 直方圖參數(shù)
    // 我們只使用 H 和 S 兩個(gè)通道
    int hBins = 50; int sBins = 60;
    int histSize[] = { hBins, sBins };

    // Hue 范圍 [0, 180], Saturation 范圍 [0, 256]
    float hRanges[] = { 0, 180 };
    float sRanges[] = { 0, 256 };
    const float* ranges[] = { hRanges, sRanges };

    // 我們計(jì)算 H 和 S 通道的直方圖
    int channels[] = { 0, 1 }; // H 通道索引為 0, S 通道索引為 1

    cv::Mat hist;
    cv::calcHist(&hsvImage, 1, channels, cv::Mat(), hist, 2, histSize, ranges, true, false);
    cv::normalize(hist, hist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

    return hist;
}


int main(int argc, char** argv) {
    if (argc < 3) {
        std::cerr << "用法: " << argv[0] << " <圖像1路徑> <圖像2路徑>" << std::endl;
        return -1;
    }

    cv::Mat image1 = cv::imread(argv[1]);
    cv::Mat image2 = cv::imread(argv[2]);

    if (image1.empty() || image2.empty()) {
        std::cerr << "錯(cuò)誤: 無法加載一張或兩張圖像!" << std::endl;
        return -1;
    }

    // 計(jì)算直方圖
    cv::Mat hist1 = calculateHSNormalizedHistogram(image1);
    cv::Mat hist2 = calculateHSNormalizedHistogram(image2);

    // 比較直方圖的方法
    // OpenCV 提供了多種比較方法,這里演示幾種常用的
    // HISTCMP_CORREL: 相關(guān)性 (值越大越相似, 范圍 [-1, 1])
    // HISTCMP_CHISQR: 卡方 (值越小越相似, 范圍 [0, inf))
    // HISTCMP_INTERSECT: 交集 (值越大越相似, 范圍 [0, sum(hist1) or sum(hist2) after normalization])
    // HISTCMP_BHATTACHARYYA: 巴氏距離 (值越小越相似, 范圍 [0, 1])

    std::cout << "直方圖比較結(jié)果:" << std::endl;

    double correlation = cv::compareHist(hist1, hist2, cv::HISTCMP_CORREL);
    std::cout << "相關(guān)性 (Correlation): " << correlation << " (越高越相似)" << std::endl;

    double chiSquare = cv::compareHist(hist1, hist2, cv::HISTCMP_CHISQR);
    std::cout << "卡方 (Chi-Square): " << chiSquare << " (越低越相似)" << std::endl;

    double intersection = cv::compareHist(hist1, hist2, cv::HISTCMP_INTERSECT);
    std::cout << "交集 (Intersection): " << intersection << " (越高越相似)" << std::endl;

    double bhattacharyya = cv::compareHist(hist1, hist2, cv::HISTCMP_BHATTACHARYYA);
    std::cout << "巴氏距離 (Bhattacharyya): " << bhattacharyya << " (越低越相似)" << std::endl;

    // 可選:顯示圖像
    cv::imshow("Image 1", image1);
    cv::imshow("Image 2", image2);
    cv::waitKey(0);
    cv::destroyAllWindows();

    return 0;
}

代碼詳解

  1. calculateHSNormalizedHistogram 函數(shù):

    • cv::cvtColor(image, hsvImage, cv::COLOR_BGR2HSV);: 將輸入的 BGR 圖像轉(zhuǎn)換為 HSV 圖像。
    • hBinssBins: 定義 H (色調(diào)) 和 S (飽和度) 通道直方圖的 bin (條柱) 的數(shù)量。
    • hRangessRanges: 定義 H 和 S 通道像素值的范圍。OpenCV 中 H 的范圍是 [0, 179],S 和 V 的范圍是 [0, 255]。
    • channels: 指定要計(jì)算直方圖的通道,這里是第 0 (H) 和第 1 (S) 通道。
    • cv::calcHist(...): 計(jì)算 H-S 二維直方圖。
      • &hsvImage: 輸入圖像的指針 (這里用數(shù)組是因?yàn)榭梢詡魅攵鄠€(gè)圖像,但我們只用一個(gè))。
      • 1: 圖像數(shù)量。
      • channels: 要統(tǒng)計(jì)的通道列表。
      • cv::Mat(): 可選的掩碼 (mask),這里不使用。
      • hist: 輸出的直方圖。
      • 2: 直方圖的維度 (因?yàn)槭?H-S 二維直方圖)。
      • histSize: 每個(gè)維度中 bin 的數(shù)量。
      • ranges: 每個(gè)維度值的范圍。
      • true: 直方圖是均勻的。
      • false: 直方圖在計(jì)算時(shí)不累積。
    • cv::normalize(hist, hist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());: 將直方圖歸一化到 [0, 1] 范圍,以便比較。
  2. main 函數(shù):

    • 加載兩張圖像。
    • 調(diào)用 calculateHSNormalizedHistogram 分別計(jì)算兩張圖像的 H-S 直方圖。
    • 使用 cv::compareHist 和不同的比較方法 (cv::HISTCMP_CORRELcv::HISTCMP_CHISQRcv::HISTCMP_INTERSECTcv::HISTCMP_BHATTACHARYYA) 比較兩個(gè)歸一化后的直方圖。
    • 打印比較結(jié)果。
    • 可選地顯示圖像。

編譯與運(yùn)行

假設(shè)你的 C++ 文件名為 histogram_comparison.cpp,并且 OpenCV 已正確配置。

Linux / macOS (使用 g++):

你需要使用 pkg-config 來獲取 OpenCV 的編譯和鏈接標(biāo)志。

g++ histogram_comparison.cpp -o histogram_comparator $(pkg-config --cflags --libs opencv4)
./histogram_comparator path/to/image1.jpg path/to/image2.jpg

如果你的 OpenCV 版本不是 4.x,或者 pkg-config 配置的是舊版本,你可能需要使用 opencv 替換 opencv4。

Windows (使用 Visual Studio):

你需要在項(xiàng)目中配置 OpenCV 的包含目錄、庫目錄,并鏈接相應(yīng)的 OpenCV 庫文件。

CMake (推薦的跨平臺方式):

創(chuàng)建一個(gè) CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.10)
project(HistogramComparator)

set(CMAKE_CXX_STANDARD 11) # 或更高版本

find_package(OpenCV REQUIRED)

include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(histogram_comparator histogram_comparison.cpp)
target_link_libraries(histogram_comparator ${OpenCV_LIBS})

然后編譯:

mkdir build && cd build
cmake ..
make # 或者在 Visual Studio 中打開生成的項(xiàng)目并編譯
./histogram_comparator path/to/image1.jpg path/to/image2.jpg

結(jié)果解讀

cv::compareHist 函數(shù)返回一個(gè) double 值,其含義取決于所選的比較方法:

  • 相關(guān)性 (cv::HISTCMP_CORREL): 結(jié)果范圍為 [-1, 1]。值越接近 1,表示兩直方圖越相似。接近 0 表示不相關(guān),接近 -1 表示負(fù)相關(guān)。
  • 卡方 (cv::HISTCMP_CHISQR): 結(jié)果范圍為 [0, ∞)。值越小,表示兩直方圖越相似。0 表示完全相同。
  • 交集 (cv::HISTCMP_INTERSECT): 對于歸一化到 [0,1] 的直方圖,如果兩個(gè)直方圖完全相同,則結(jié)果為1 (如果未歸一化到和為1,則為直方圖的總 bin 數(shù)或像素?cái)?shù))。值越大,表示重疊部分越多,越相似。
  • 巴氏距離 (cv::HISTCMP_BHATTACHARYYA): 結(jié)果范圍為 [0, 1]。值越小,表示兩直方圖越相似。0 表示完全相同。

根據(jù)應(yīng)用場景選擇合適的比較方法。例如,相關(guān)性和交集是衡量相似度的,而卡方和巴氏距離是衡量差異度的。

總結(jié)與擴(kuò)展

直方圖比較提供了一種快速評估圖像顏色分布相似性的方法。雖然它不考慮空間信息(即像素在哪里),但在許多場景下仍然非常有用。

可擴(kuò)展的方向包括:

  • 不同顏色空間: 嘗試在 BGR 或 Lab 等其他顏色空間計(jì)算直方圖。
  • 一維直方圖: 可以為每個(gè)顏色通道分別計(jì)算一維直方圖,然后組合比較結(jié)果。
  • 加權(quán)直方圖: 在計(jì)算直方圖時(shí),可以根據(jù)像素位置或其他特征給予不同的權(quán)重。
  • 結(jié)合其他特征: 將直方圖特征與其他圖像特征(如紋理、形狀)結(jié)合起來,以獲得更魯棒的圖像比較。
  • 自適應(yīng) bin 數(shù)量: 根據(jù)圖像內(nèi)容動態(tài)調(diào)整直方圖的 bin 數(shù)量。

希望本文能幫助你理解并使用 OpenCV 進(jìn)行圖像直方圖比較!

以上就是利用C++和OpenCV庫計(jì)算圖像顏色直方圖并比較相似度的詳細(xì)內(nèi)容,更多關(guān)于C++ OpenCV圖像直方圖和相似度的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++標(biāo)準(zhǔn)模板庫map的常用操作

    C++標(biāo)準(zhǔn)模板庫map的常用操作

    今天小編就為大家分享一篇關(guān)于C++標(biāo)準(zhǔn)模板庫map的常用操作,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C++中的模板類&模板函數(shù)

    C++中的模板類&模板函數(shù)

    這篇文章主要介紹了C++中的模板類&模板函數(shù)用法,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • C++ Boost Heap使用實(shí)例詳解

    C++ Boost Heap使用實(shí)例詳解

    Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個(gè)可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱
    2022-11-11
  • boost.asio框架系列之調(diào)度器io_service

    boost.asio框架系列之調(diào)度器io_service

    這篇文章介紹了boost.asio框架系列之調(diào)度器io_service,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Matlab利用隨機(jī)森林(RF)算法實(shí)現(xiàn)回歸預(yù)測詳解

    Matlab利用隨機(jī)森林(RF)算法實(shí)現(xiàn)回歸預(yù)測詳解

    這篇文章主要為大家詳細(xì)介紹了Matlab如何利用隨機(jī)森林(RF)算法實(shí)現(xiàn)回歸預(yù)測,以及自變量重要性排序的操作,感興趣的小伙伴可以了解一下
    2023-02-02
  • C語言實(shí)現(xiàn)水波紋效果

    C語言實(shí)現(xiàn)水波紋效果

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)水波紋效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • c++禁止函數(shù)的傳值調(diào)用的方法

    c++禁止函數(shù)的傳值調(diào)用的方法

    這篇文章主要介紹了c++禁止函數(shù)的傳值調(diào)用的方法,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-08-08
  • C++實(shí)現(xiàn)自頂向下的歸并排序算法

    C++實(shí)現(xiàn)自頂向下的歸并排序算法

    這篇文章主要介紹了C++實(shí)現(xiàn)自頂向下的歸并排序算法,結(jié)合實(shí)例詳細(xì)分析了自頂向下的歸并排序算法的原理與具體實(shí)現(xiàn)步驟,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-12-12
  • C++與C#互調(diào)dll的實(shí)現(xiàn)步驟

    C++與C#互調(diào)dll的實(shí)現(xiàn)步驟

    這篇文章主要介紹了C++與C#互調(diào)dll的實(shí)現(xiàn)步驟,dll動態(tài)鏈接庫的共享在一些大型項(xiàng)目中有一定的應(yīng)用價(jià)值,需要的朋友可以參考下
    2014-08-08
  • C++ main函數(shù)中的argc與argv全面解析

    C++ main函數(shù)中的argc與argv全面解析

    C/C++中的main函數(shù)可以接受命令行參數(shù),通過argc和argv來傳遞這些參數(shù),argc表示參數(shù)總數(shù),argv是一個(gè)字符串?dāng)?shù)組,包含具體的參數(shù),本文介紹C++ main函數(shù)中的argc與argv,感興趣的朋友跟隨小編一起看看吧
    2026-03-03

最新評論

新安县| 浦北县| 澳门| 汉川市| 古田县| 岳池县| 手游| 什邡市| 商都县| 蚌埠市| 怀集县| 华亭县| 巴青县| 东城区| 宣恩县| 海门市| 改则县| 柘城县| 大连市| 嘉峪关市| 清徐县| 潼关县| 城固县| 吐鲁番市| 正镶白旗| 仁寿县| 安阳市| 玉龙| 沙坪坝区| 晋城| 桓台县| 宁陕县| 邮箱| 新乡市| 伽师县| 门源| 固镇县| 楚雄市| 瑞丽市| 宜川县| 佛冈县|