欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

簡介

圖像直方圖是圖像中像素強(qiáng)度分布的圖形表示。對(duì)于彩色 圖像,我們通常會(huì)為每個(gè)顏色通道(例如 BGR 或 HSV)計(jì)算直方圖。通過比較兩張圖片的直方圖,我們可以獲得它們?cè)陬伾植忌系南嗨瞥潭取penCV 提供了 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 對(duì)光照變化的魯棒性通常比 BGR 好,尤其是 H (Hue) 和 S (Saturation) 通道。
  3. 計(jì)算直方圖:
    • 定義直方圖參數(shù)(如通道、bins 數(shù)量、取值范圍)。
    • 使用 cv::calcHist 為每張圖像計(jì)算 H-S 二維直方圖或單個(gè)通道的一維直方圖。
  4. 歸一化直方圖 (可選但推薦): 為了消除圖像尺寸差異帶來的影響,通常會(huì)對(duì)直方圖進(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 (推薦的跨平臺(tái)方式):

創(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): 對(duì)于歸一化到 [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ò)展

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

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

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

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

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

相關(guān)文章

  • 純C語言:分治問題源碼分享

    純C語言:分治問題源碼分享

    這篇文章主要介紹了純C語言:分治問題源碼,有需要的朋友可以參考一下
    2014-01-01
  • Linux?C/C++實(shí)現(xiàn)網(wǎng)絡(luò)流量分析工具

    Linux?C/C++實(shí)現(xiàn)網(wǎng)絡(luò)流量分析工具

    網(wǎng)絡(luò)流量分析的原理基于對(duì)數(shù)據(jù)包的捕獲、解析和統(tǒng)計(jì)分析,通過對(duì)網(wǎng)絡(luò)流量的細(xì)致觀察和分析,幫助管理員了解和優(yōu)化網(wǎng)絡(luò)的性能,本文將通過C++實(shí)現(xiàn)網(wǎng)絡(luò)流量分析工具,有需要的可以參考下
    2023-10-10
  • C++樹之遍歷二叉樹實(shí)例詳解

    C++樹之遍歷二叉樹實(shí)例詳解

    這篇文章主要給大家介紹了關(guān)于C++樹之遍歷二叉樹的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Vscode配置C/C++環(huán)境使用minGW(保姆級(jí)配置過程)

    Vscode配置C/C++環(huán)境使用minGW(保姆級(jí)配置過程)

    本文主要介紹了Vscode配置C/C++環(huán)境使用minGW(保姆級(jí)配置過程),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C語言必背的一些經(jīng)典程序代碼實(shí)例

    C語言必背的一些經(jīng)典程序代碼實(shí)例

    C語言是一種高級(jí)編程語言,具有很多優(yōu)點(diǎn),下面這篇文章主要給大家介紹了關(guān)于C語言必背的一些經(jīng)典程序代碼,文中通過詳細(xì)的實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • C++實(shí)現(xiàn)LeetCode(125.驗(yàn)證回文字符串)

    C++實(shí)現(xiàn)LeetCode(125.驗(yàn)證回文字符串)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(驗(yàn)證回文字符串).本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Visual Studio 如何創(chuàng)建C/C++項(xiàng)目問題

    Visual Studio 如何創(chuàng)建C/C++項(xiàng)目問題

    這篇文章主要介紹了Visual Studio 如何創(chuàng)建C/C++項(xiàng)目問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C語言的基本語法詳解

    C語言的基本語法詳解

    本篇文章主要講解C語言 基本語法,這里提供簡單的示例和代碼來詳細(xì)講解C語言的基本語法,開始學(xué)習(xí)C語言的朋友可以看一下,希望能夠給你帶來幫助
    2021-09-09
  • C++ Opencv自寫函數(shù)實(shí)現(xiàn)膨脹腐蝕處理技巧

    C++ Opencv自寫函數(shù)實(shí)現(xiàn)膨脹腐蝕處理技巧

    這篇文章主要介紹了C++ Opencv 自寫函數(shù)實(shí)現(xiàn)膨脹腐蝕處理,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • Qt中PaintEvent繪制實(shí)時(shí)波形圖的實(shí)現(xiàn)示例

    Qt中PaintEvent繪制實(shí)時(shí)波形圖的實(shí)現(xiàn)示例

    本文主要介紹了Qt中PaintEvent繪制實(shí)時(shí)波形圖的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06

最新評(píng)論