c/c++的opencv的圖像預處理講解

OpenCV 圖像預處理核心技術詳解 (C/C++)

圖像預處理是計算機視覺任務中至關重要的一步。原始圖像往往受到噪聲、光照不均、尺寸不一等多種因素的影響,直接用于后續分析(如特征提取、目標檢測、機器學習模型訓練等)可能會導致性能下降或結果不準確。預處理旨在通過一系列操作來增強圖像質量、去除噪聲、標準化圖像數據,使其更適合特定應用。

本文將詳細介紹幾種 OpenCV 中常用的圖像預處理技術,包括其 C/C++ 實現、關鍵參數解析以及使用時的注意事項。


目錄

  1. 灰度轉換 (Grayscale Conversion)
  2. 圖像縮放 (Resizing)
  3. 圖像平滑/模糊 (Smoothing/Blurring)
    • 高斯模糊 (Gaussian Blur)
    • 中值模糊 (Median Blur)
    • 雙邊濾波 (Bilateral Filter)
  4. 閾值化處理 (Thresholding)
    • 簡單閾值 (Simple Thresholding)
    • 自適應閾值 (Adaptive Thresholding)
  5. 圖像歸一化 (Normalization)
  6. 形態學操作 (Morphological Operations)
    • 腐蝕 (Erosion) 與膨脹 (Dilation)
    • 開運算 (Opening) 與閉運算 (Closing)
  7. 直方圖均衡化 (Histogram Equalization)
  8. 總結與建議

1. 灰度轉換 (Grayscale Conversion)

將彩色圖像轉換為灰度圖像是最常見的預處理步驟之一。

  • 目的:降低數據維度(從3通道變為1通道),減少計算量,某些算法(如Canny邊緣檢測)通常在灰度圖上操作。
  • OpenCV 函數cv::cvtColor()
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp> // 包含 cvtColorint main() {cv::Mat src = cv::imread("input.jpg", cv::IMREAD_COLOR);if (src.empty()) {std::cerr << "Error: Image cannot be loaded!" << std::endl;return -1;}cv::Mat gray;cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY); // 注意OpenCV默認加載為BGRcv::imshow("Original", src);cv::imshow("Grayscale", gray);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::cvtColor):

  • src: 輸入圖像 (彩色圖像)。
  • dst: 輸出圖像 (灰度圖像)。
  • code: 顏色空間轉換代碼。
    • cv::COLOR_BGR2GRAY: 從 BGR (OpenCV 默認的彩色圖像通道順序) 轉換為灰度。
    • cv::COLOR_RGB2GRAY: 從 RGB 轉換為灰度 (如果你的圖像源是 RGB)。
    • cv::COLOR_BGR2HSV: 轉換為 HSV 顏色空間等。

注意事項:

  • 確保輸入圖像確實是彩色圖像。對已經是灰度的圖像進行此操作通常不會報錯,但無意義。
  • OpenCV 使用 cv::imread() 加載圖像時,默認通道順序是 BGR。如果你的圖像數據來自其他源(例如某些庫或傳感器可能輸出 RGB),請注意選擇正確的轉換代碼。

2. 圖像縮放 (Resizing)

調整圖像的尺寸以滿足特定算法的輸入要求或減少計算量。

  • 目的:統一輸入尺寸,構建圖像金字塔,加速處理。
  • OpenCV 函數cv::resize()
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp> // 包含 resizeint main() {cv::Mat src = cv::imread("input.jpg");if (src.empty()) {std::cerr << "Error: Image cannot be loaded!" << std::endl;return -1;}cv::Mat resized_abs, resized_rel;cv::Size new_size(300, 200); // 目標絕對尺寸:寬300, 高200// 方法1: 指定目標尺寸cv::resize(src, resized_abs, new_size, 0, 0, cv::INTER_LINEAR);// 方法2: 指定縮放因子double scale_x = 0.5;double scale_y = 0.5;cv::resize(src, resized_rel, cv::Size(), scale_x, scale_y, cv::INTER_LINEAR);cv::imshow("Original", src);cv::imshow("Resized (Absolute)", resized_abs);cv::imshow("Resized (Relative)", resized_rel);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::resize):

  • src: 輸入圖像。
  • dst: 輸出圖像。
  • dsize: 輸出圖像的目標尺寸 (cv::Size(width, height))。如果設置為 cv::Size() (即 cv::Size(0,0)),則尺寸將通過 fxfy 計算。
  • fx: 沿水平軸的縮放因子。如果 dsize 非零,則此參數無效。
  • fy: 沿垂直軸的縮放因子。如果 dsize 非零,則此參數無效。
  • interpolation: 插值方法。
    • cv::INTER_NEAREST: 最近鄰插值。速度最快,但效果可能較差,有馬賽克感。
    • cv::INTER_LINEAR: 雙線性插值 (默認)。速度和效果的良好折中,常用于放大。
    • cv::INTER_CUBIC: 雙三次插值。效果較好,尤其在放大時,但計算量更大。
    • cv::INTER_AREA: 基于區域的重采樣。在縮小圖像時效果較好,可以避免波紋。放大時類似最近鄰。
    • cv::INTER_LANCZOS4: Lanczos 插值 (8x8鄰域)。效果最好,但計算量最大。

注意事項:

  • 插值方法選擇:
    • 縮小圖像時,cv::INTER_AREA 通常是最佳選擇,以避免信息丟失和摩爾紋。
    • 放大圖像時,cv::INTER_LINEAR 是一個不錯的起點,cv::INTER_CUBICcv::INTER_LANCZOS4 可以提供更好的質量,但更慢。
  • 長寬比: 如果只指定 dsize 而不考慮原始長寬比,圖像可能會變形。如果需要保持長寬比,應先計算一個軸的縮放因子或新尺寸,然后據此計算另一個。
  • 如果同時提供了 dsize (非零) 和 fx/fy (非零),dsize 優先。

3. 圖像平滑/模糊 (Smoothing/Blurring)

用于減少圖像噪聲,平滑圖像細節。

高斯模糊 (Gaussian Blur)

使用高斯核對圖像進行卷積,有效去除高斯噪聲。

  • OpenCV 函數cv::GaussianBlur()
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("input_noisy.jpg"); // 假設有一張帶噪聲的圖if (src.empty()) { /* ... error handling ... */ return -1; }cv::Mat blurred_gaussian;cv::Size kernel_size(5, 5); // 高斯核尺寸,必須是正奇數double sigmaX = 0; // X方向標準差,若為0,則由ksize.width計算// double sigmaY = 0; // Y方向標準差,若為0,則由ksize.height計算 (或等于sigmaX)cv::GaussianBlur(src, blurred_gaussian, kernel_size, sigmaX);cv::imshow("Original", src);cv::imshow("Gaussian Blurred", blurred_gaussian);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::GaussianBlur):

  • ksize: 高斯核的尺寸 (cv::Size(width, height))。寬度和高度必須是正奇數,也可以不同。
  • sigmaX: X 方向的高斯核標準差。
  • sigmaY: Y 方向的高斯核標準差。如果為0,則設置成與 sigmaX 相同;如果兩者都為0,則它們從 ksize.widthksize.height 計算得出。建議將 sigmaY 設為0,讓其自動等于 sigmaX 或根據 ksize 計算。
  • borderType: 邊界處理方式,默認 cv::BORDER_DEFAULT

注意事項 (GaussianBlur):

  • ksize 越大,圖像越模糊。sigmaX (和 sigmaY) 越大,模糊程度也越大。
  • 如果 sigmaX (和 sigmaY) 設置得非常小,而 ksize 較大,效果可能不佳。通常讓 sigma 根據 ksize 計算 (通過將 sigmaX 設為0) 是個好主意,或者根據經驗值設定。
  • 高斯模糊對所有方向的平滑程度相同,可能會模糊掉一些有用的邊緣信息。

中值模糊 (Median Blur)

用像素鄰域內的中值替換該像素的值,對椒鹽噪聲特別有效。

  • OpenCV 函數cv::medianBlur()
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("salt_pepper_noise.jpg"); // 假設有椒鹽噪聲圖if (src.empty()) { /* ... error handling ... */ return -1; }cv::Mat blurred_median;int ksize_median = 5; // 孔徑線性尺寸,必須是大于1的奇數cv::medianBlur(src, blurred_median, ksize_median);cv::imshow("Original", src);cv::imshow("Median Blurred", blurred_median);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::medianBlur):

  • ksize: 孔徑的線性尺寸 (例如,5 表示 5x5 的鄰域)。必須是大于1的奇數。

注意事項 (medianBlur):

  • ksize 越大,平滑效果越強,但也可能丟失更多圖像細節。
  • 相比高斯模糊,中值模糊在去除椒鹽噪聲的同時能更好地保留邊緣。
  • 計算開銷隨 ksize 增加而顯著增加。

雙邊濾波 (Bilateral Filter)

在平滑圖像的同時保持邊緣清晰。

  • OpenCV 函數cv::bilateralFilter()
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("input.jpg");if (src.empty()) { /* ... error handling ... */ return -1; }cv::Mat blurred_bilateral;int d = 9;              // 濾波期間每個像素鄰域的直徑。如果非正,則從 sigmaSpace 計算。double sigmaColor = 75; // 顏色空間濾波器的 Sigma 值。較大值意味著鄰域內更遠的顏色也會混合在一起,從而產生更大區域的半相等顏色。double sigmaSpace = 75; // 坐標空間濾波器的 Sigma 值。較大值意味著更遠的像素將相互影響,只要它們的顏色足夠接近。當 d>0 時,它指定鄰域大小而不考慮 sigmaSpace。否則,d 與 sigmaSpace 成正比。cv::bilateralFilter(src, blurred_bilateral, d, sigmaColor, sigmaSpace);cv::imshow("Original", src);cv::imshow("Bilateral Filtered", blurred_bilateral);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::bilateralFilter):

  • d: 在過濾期間使用的每個像素鄰域的直徑。如果為非正數(例如 -1),則會從 sigmaSpace 計算出來。通常取 5 到 9 之間的值。
  • sigmaColor: 顏色空間的標準差。值越大,意味著越多差異較大的顏色會被認為是相似的,從而被平均。
  • sigmaSpace: 坐標空間的標準差。值越大,意味著越遠的像素會相互影響(只要顏色相似)。如果 d > 0,則 d 指定鄰域大小,sigmaSpace 不起作用;否則 dsigmaSpace 成正比。

注意事項 (bilateralFilter):

  • 雙邊濾波比其他模糊方法慢得多。
  • 參數 sigmaColorsigmaSpace 的調整對結果影響很大,需要根據具體圖像和需求進行調試。
  • 如果 sigmaColor 值過大,效果接近高斯模糊;如果過小,則平滑效果不明顯。
  • 如果 sigmaSpace 值過大,計算量會增加。

4. 閾值化處理 (Thresholding)

將圖像轉換為二值圖像(通常是黑白)。

簡單閾值 (Simple Thresholding)

將像素值與固定閾值進行比較。

  • OpenCV 函數cv::threshold()
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE); // 閾值處理通常在灰度圖上進行if (src.empty()) { /* ... error handling ... */ return -1; }cv::Mat thresh_binary, thresh_otsu;double thresh_val = 127;double max_val = 255;// 基本二值閾值cv::threshold(src, thresh_binary, thresh_val, max_val, cv::THRESH_BINARY);// Otsu's 二值化 (自動計算閾值)// 此時,輸入的 thresh_val (這里是0) 被忽略,函數會自動計算最佳閾值double otsu_thresh = cv::threshold(src, thresh_otsu, 0, max_val, cv::THRESH_BINARY | cv::THRESH_OTSU);std::cout << "Otsu's calculated threshold: " << otsu_thresh << std::endl;cv::imshow("Original Grayscale", src);cv::imshow("Binary Threshold", thresh_binary);cv::imshow("Otsu's Threshold", thresh_otsu);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::threshold):

  • src: 輸入圖像,通常是單通道灰度圖。
  • dst: 輸出的二值圖像。
  • thresh: 閾值。
  • maxval: 當像素值超過(或滿足某些條件,取決于 type)閾值時賦予的新值。
  • type: 閾值類型:
    • cv::THRESH_BINARY: 如果 src(x,y) > thresh,則 dst(x,y) = maxval,否則 dst(x,y) = 0
    • cv::THRESH_BINARY_INV: cv::THRESH_BINARY 的反轉。
    • cv::THRESH_TRUNC: 如果 src(x,y) > thresh,則 dst(x,y) = thresh,否則 dst(x,y) = src(x,y)
    • cv::THRESH_TOZERO: 如果 src(x,y) > thresh,則 dst(x,y) = src(x,y),否則 dst(x,y) = 0
    • cv::THRESH_TOZERO_INV: cv::THRESH_TOZERO 的反轉。
    • cv::THRESH_OTSU: Otsu’s 二值化。與上述類型之一(通常是 cv::THRESH_BINARY)通過 | (位或) 組合使用。函數會自動計算一個全局最優閾值。此時 thresh 參數被忽略。
    • cv::THRESH_TRIANGLE: Triangle 算法,也用于自動閾值確定。

注意事項 (threshold):

  • 輸入圖像應為灰度圖。
  • cv::THRESH_OTSUcv::THRESH_TRIANGLE 對于雙峰直方圖的圖像效果較好,可以自動找到合適的閾值,但對光照不均的圖像可能效果不佳。
  • 選擇合適的 thresh 值對于簡單閾值至關重要,通常需要實驗或基于圖像直方圖分析。

自適應閾值 (Adaptive Thresholding)

對于光照不均的圖像,使用局部閾值而非全局閾值。

  • OpenCV 函數cv::adaptiveThreshold()
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("uneven_lighting.jpg", cv::IMREAD_GRAYSCALE); // 假設光照不均if (src.empty()) { /* ... error handling ... */ return -1; }cv::Mat adaptive_thresh_mean, adaptive_thresh_gaussian;double max_val = 255;int block_size = 11; // 鄰域大小,必須是奇數double C = 2;        // 從均值或加權均值中減去的常數cv::adaptiveThreshold(src, adaptive_thresh_mean, max_val,cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY,block_size, C);cv::adaptiveThreshold(src, adaptive_thresh_gaussian, max_val,cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY,block_size, C);cv::imshow("Original Grayscale", src);cv::imshow("Adaptive Mean Threshold", adaptive_thresh_mean);cv::imshow("Adaptive Gaussian Threshold", adaptive_thresh_gaussian);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::adaptiveThreshold):

  • src: 輸入灰度圖像。
  • dst: 輸出二值圖像。
  • maxValue: 賦予超過閾值的像素的新值。
  • adaptiveMethod: 自適應閾值算法:
    • cv::ADAPTIVE_THRESH_MEAN_C: 閾值是鄰域的均值減去 C
    • cv::ADAPTIVE_THRESH_GAUSSIAN_C: 閾值是鄰域的高斯加權和減去 C
  • thresholdType: 閾值類型,通常是 cv::THRESH_BINARYcv::THRESH_BINARY_INV
  • blockSize: 用于計算閾值的像素鄰域大小,必須是奇數。
  • C: 從均值或加權均值中減去的常數。可以是正數、零或負數。

注意事項 (adaptiveThreshold):

  • blockSizeC 的選擇對結果影響很大,需要仔細調整。
  • blockSize 越大,參與計算局部閾值的區域就越大,細節可能會丟失。太小則可能對噪聲敏感。
  • cv::ADAPTIVE_THRESH_GAUSSIAN_C 通常比 cv::ADAPTIVE_THRESH_MEAN_C 效果更好,因為它對中心點附近的像素賦予更大權重。

5. 圖像歸一化 (Normalization)

將像素值縮放到特定范圍,例如 [0, 1] 或 [0, 255]。

  • 目的:消除由于光照和對比度不同帶來的影響,改善某些算法(如機器學習模型)的性能。
  • OpenCV 函數cv::normalize()
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp> // 包含 normalizeint main() {// 假設我們有一個CV_32F類型的圖像(例如,某些算法的輸出)cv::Mat src = cv::Mat::zeros(100, 100, CV_32FC1);cv::randu(src, cv::Scalar::all(50), cv::Scalar::all(200)); // 填充50-200之間的隨機值cv::Mat normalized_img;double alpha = 0;   // 歸一化后的最小值double beta = 255;  // 歸一化后的最大值 (對于顯示,通常是255)// 對于機器學習特征,可能是1.0// 歸一化到 [alpha, beta] 范圍cv::normalize(src, normalized_img, alpha, beta, cv::NORM_MINMAX, CV_8UC1); // 輸出為CV_8UC1用于顯示// 如果只是想歸一化到 [0,1] 并且保持浮點類型cv::Mat normalized_float;cv::normalize(src, normalized_float, 0.0, 1.0, cv::NORM_MINMAX, CV_32FC1);// 顯示需要轉換到8位cv::Mat src_display, norm_display;if (src.type() != CV_8U) src.convertTo(src_display, CV_8U, 255.0/(200-50), -50.0 * 255.0/(200-50)); // 手動調整范圍以便顯示else src.copyTo(src_display);normalized_img.copyTo(norm_display); // normalized_img 已經是 CV_8UC1cv::imshow("Original (scaled for display)", src_display);cv::imshow("Normalized to [0, 255]", norm_display);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::normalize):

  • src: 輸入數組。
  • dst: 輸出數組,與 src 大小相同。
  • alpha: 范圍歸一化的下界。
  • beta: 范圍歸一化的上界 (對于 cv::NORM_MINMAX) 或范數值 (對于其他類型)。
  • norm_type: 歸一化類型:
    • cv::NORM_MINMAX: 將值線性縮放到 [alpha, beta] 范圍。
    • cv::NORM_INF, cv::NORM_L1, cv::NORM_L2: 按指定范數進行歸一化 (通常 beta 用作目標范數值)。
  • dtype: 當為負數時,輸出數組 dst 的類型與 src 相同;否則,它與 src 的通道數相同,但深度為 dtype。例如,可以將 CV_32F 歸一化為 CV_8U。
  • mask: 可選的操作掩碼。

注意事項 (normalize):

  • 最常用的歸一化類型是 cv::NORM_MINMAX
  • 如果 dtype 設置為輸出特定類型(如 CV_8U),則會進行類型轉換和可能的截斷/縮放。
  • 在進行某些特征描述子計算或將圖像輸入到神經網絡之前,歸一化非常重要。

6. 形態學操作 (Morphological Operations)

基于形狀改變圖像結構的非線性操作,常用于噪聲去除、物體分離/連接、尋找區域等。

  • 核心元素: 結構元素 (Kernel/Structuring Element),它定義了操作的鄰域形狀。
    • 使用 cv::getStructuringElement(shape, ksize, anchor) 創建。
      • shape: cv::MORPH_RECT (矩形), cv::MORPH_ELLIPSE (橢圓), cv::MORPH_CROSS (十字形)。
      • ksize: 結構元素的尺寸。
      • anchor: 錨點位置,默認在中心。

腐蝕 (Erosion) 與膨脹 (Dilation)

  • 腐蝕 (cv::erode): “收縮” 或 “細化” 圖像中的亮區(前景)。去除小的噪點。
  • 膨脹 (cv::dilate): “擴張” 或 “加粗” 圖像中的亮區。連接斷開的部分,填充孔洞。
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("binary_image.png", cv::IMREAD_GRAYSCALE); // 最好是二值圖或灰度圖if (src.empty()) { /* ... error handling ... */ return -1; }// 確保是二值圖像 (例如,經過閾值化處理)cv::threshold(src, src, 127, 255, cv::THRESH_BINARY);cv::Mat eroded, dilated;cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));// int iterations = 1; // 操作迭代次數cv::erode(src, eroded, kernel);cv::dilate(src, dilated, kernel);cv::imshow("Original Binary", src);cv::imshow("Eroded", eroded);cv::imshow("Dilated", dilated);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::erode, cv::dilate):

  • src: 輸入圖像。
  • dst: 輸出圖像。
  • kernel: 結構元素。如果為 cv::Mat(),則使用 3x3 矩形核。
  • anchor: 錨點位置,默認 cv::Point(-1,-1) 表示在核中心。
  • iterations: 操作迭代次數。次數越多,效果越明顯。
  • borderType, borderValue: 邊界處理。

開運算 (Opening) 與閉運算 (Closing)

通過組合腐蝕和膨脹實現更復雜的操作。使用 cv::morphologyEx()

  • 開運算 (cv::MORPH_OPEN): 先腐蝕后膨脹。用于去除小的噪點(暗背景上的亮噪點),平滑物體輪廓,斷開細小連接。
  • 閉運算 (cv::MORPH_CLOSE): 先膨脹后腐蝕。用于填充物體內的小孔洞,連接鄰近物體,平滑輪廓。
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("noisy_binary.png", cv::IMREAD_GRAYSCALE);if (src.empty()) { /* ... error handling ... */ return -1; }cv::threshold(src, src, 127, 255, cv::THRESH_BINARY);cv::Mat opened, closed;cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(7, 7));cv::morphologyEx(src, opened, cv::MORPH_OPEN, kernel);cv::morphologyEx(src, closed, cv::MORPH_CLOSE, kernel);cv::imshow("Original Binary", src);cv::imshow("Opened", opened);cv::imshow("Closed", closed);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析 (cv::morphologyEx):

  • op: 形態學操作類型:
    • cv::MORPH_OPEN, cv::MORPH_CLOSE
    • cv::MORPH_GRADIENT: 膨脹圖與腐蝕圖之差,可得到物體輪廓。
    • cv::MORPH_TOPHAT: 原圖與開運算結果之差。
    • cv::MORPH_BLACKHAT: 閉運算結果與原圖之差。
  • 其他參數與 erode/dilate 類似。

注意事項 (形態學操作):

  • 通常在二值圖像上操作效果最直觀,但也可用于灰度圖像。
  • 結構元素 kernel 的形狀和大小對結果影響極大。矩形核適用于處理具有水平和垂直邊緣的結構;橢圓或圓形核更通用。
  • iterations 參數可以增強效果,但多次小核操作不完全等同于一次大核操作。

7. 直方圖均衡化 (Histogram Equalization)

增強圖像對比度,尤其對那些像素值集中在某個狹窄范圍內的圖像有效。

  • 目的:擴展圖像的像素強度分布,使其更均勻地覆蓋整個強度范圍。
  • OpenCV 函數:
    • cv::equalizeHist(): 全局直方圖均衡化。
    • cv::CLAHE: 對比度受限的自適應直方圖均衡化 (Contrast Limited Adaptive Histogram Equalization)。
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>int main() {cv::Mat src = cv::imread("low_contrast.jpg", cv::IMREAD_GRAYSCALE); // 假設低對比度圖if (src.empty()) { /* ... error handling ... */ return -1; }cv::Mat equalized_global;cv::equalizeHist(src, equalized_global);cv::Mat equalized_clahe;// 創建 CLAHE 對象// double clipLimit = 2.0; // 對比度限制閾值// cv::Size tileGridSize(8, 8); // 將圖像劃分為的小塊數量cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE();clahe->setClipLimit(2.0);clahe->setTileGridSize(cv::Size(8, 8));clahe->apply(src, equalized_clahe);cv::imshow("Original Grayscale", src);cv::imshow("Global Histogram Equalization", equalized_global);cv::imshow("CLAHE", equalized_clahe);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

參數解析:

  • cv::equalizeHist(src, dst):

    • src: 輸入8位單通道圖像 (灰度圖)。
    • dst: 輸出均衡化后的圖像。
  • cv::createCLAHE(clipLimit, tileGridSize):

    • clipLimit: 對比度限制。較高的值允許更大的對比度。如果噪聲是問題,可以減小它。默認40.0。
    • tileGridSize: 將圖像分割成的小塊(tile)的網格尺寸。例如 cv::Size(8,8) 表示 8x8 的小塊。在每個小塊內進行直方圖均衡化。

注意事項:

  • cv::equalizeHist() 是全局操作,可能會導致某些區域的對比度過度增強,并放大噪聲。
  • CLAHE 是局部操作,將圖像分成小塊,在每個小塊內進行直方圖均衡化,然后通過雙線性插值拼接,通常效果更好,能有效限制對比度放大,減少噪聲。
  • CLAHEclipLimittileGridSize 參數需要根據圖像內容調整。
  • 這些操作通常用于灰度圖像。若要用于彩色圖像,可以先轉換到如 HSV 或 Lab 等顏色空間,對亮度通道 (V 或 L) 進行均衡化,然后再轉換回 BGR。

8. 總結與建議

圖像預處理是一個實驗性很強的過程,沒有萬能的方法。

  • 理解你的數據: 分析圖像的特點(噪聲類型、光照條件、尺寸變化等)。
  • 明確你的目標: 預處理的目的是服務于后續任務。不同的任務可能需要不同的預處理組合。
  • 參數調整: 大多數預處理函數的參數對結果影響顯著,需要耐心調試和比較。
  • 順序問題: 預處理步驟的順序也很重要。例如,通常先去噪再進行邊緣檢測或閾值化。
  • 可視化: 始終可視化每一步預處理的結果,以便直觀判斷效果。
  • 適度原則: 過度的預處理可能會丟失有用信息。

從這些基礎操作開始,你可以構建復雜的預處理流水線來應對各種計算機視覺挑戰。祝你在 OpenCV 的學習和應用中取得成功!


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/80165.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/80165.shtml
英文地址,請注明出處:http://en.pswp.cn/web/80165.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用 Docker 部署 React + Nginx 應用教程

目錄 1. 創建react項目結構2. 創建 .dockerignore3. 創建 Dockerfile4. 創建 nginx.conf5. 構建和運行6. 常用命令 1. 創建react項目結構 2. 創建 .dockerignore # 依賴目錄 node_modules npm-debug.log# 構建輸出 dist build# 開發環境文件 .git .gitignore .env .env.local …

Java 流(Stream)API

一、理論說明 1. 流的定義 Java 流&#xff08;Stream&#xff09;是 Java 8 引入的新特性&#xff0c;用于對集合&#xff08;如 List、Set&#xff09;或數組進行高效的聚合操作&#xff08;如過濾、映射、排序&#xff09;和并行處理。流不存儲數據&#xff0c;而是按需計…

網絡協議分析 實驗七 FTP、HTTP、DHCP

文章目錄 實驗7.1 FTP協議練習二 使用瀏覽器登入FTP練習三 在窗口模式下&#xff0c;上傳/下傳數據文件實驗7.2 HTTP(Hyper Text Transfer Protocol)練習二 頁面提交練習三 訪問比較復雜的主頁實驗7.3 DHCP(Dynamic Host Configuration Protocol) 實驗7.1 FTP協議 dir LIST&…

go語言學習進階

目錄 第一章 go語言中包的使用 一.main包 二.package 三.import 四.goPath環境變量 五.init包初始化 六.管理外部包 第二章 time包 第三章 File文件操作 一.FileInfo接口 二.權限 三.打開模式 四.File操作 五.讀文件 參考1&#xff1a;Golang 中的 bufio 包詳解…

Hue面試內容整理-后端框架

Cloudera 的 Hue 項目在后端采用了成熟的 Python Web 框架 Django,結合其他組件構建了一個可擴展、模塊化的系統,便于與 Hadoop 生態系統中的各個組件集成。以下是 Hue 后端架構的詳細介紹: 后端架構概覽 1. Django Web 框架 Hue 的核心是基于 Django 構建的 Web 應用,負責…

Web-CSS入門

WEB前端&#xff0c;三部分&#xff1a;HTML部分、CSS部分、Javascript部分。 1.HTML部分&#xff1a;主要負責網頁的結構層 2.CSS部分&#xff1a;主要負責網頁的樣式層 3.JS部分&#xff1a;主要負責網頁的行為層 **基本概念** 層疊樣式表&#xff0c;Cascading Style Sh…

2025年PMP 學習十六 第11章 項目風險管理 (總章)

2025年PMP 學習十六 第11章 項目風險管理 &#xff08;總章&#xff09; 第11章 項目風險管理 序號過程過程組1規劃風險管理規劃2識別風險規劃3實施定性風險分析規劃4實施定量風險分析規劃5規劃風險應對執行6實施風險應對執行7監控風險監控 目標: 提高項目中積極事件的概率和…

基于SpringBoot的小區停車位管理系統

作者&#xff1a;計算機學姐 開發技術&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源碼”。 專欄推薦&#xff1a;前后端分離項目源碼、SpringBoot項目源碼、Vue項目源碼、SSM項目源碼、微信小程序源碼 精品專欄&#xff1a;…

HTML常用標簽用法全解析:構建語義化網頁的核心指南

HTML作為網頁開發的基石&#xff0c;其標簽的合理使用直接影響頁面的可讀性、SEO效果及維護性。本文系統梳理HTML核心標簽的用法&#xff0c;結合語義化設計原則與實戰示例&#xff0c;助你構建規范、高效的網頁結構。 一、基礎結構與排版標簽 1.1 文檔結構 <!DOCTYPE htm…

國產linux系統(銀河麒麟,統信uos)使用 PageOffice自定義Word模版中的數據區域

? PageOffice 國產版 &#xff1a;支持信創系統&#xff0c;支持銀河麒麟V10和統信UOS&#xff0c;支持X86&#xff08;intel、兆芯、海光等&#xff09;、ARM&#xff08;飛騰、鯤鵬、麒麟等&#xff09;、龍芯&#xff08;Mips、LoogArch&#xff09;芯片架構。 在實際的Wor…

.NET Core liunx二進制文件安裝

最近遇見個尷尬的事情&#xff0c;都2025年了。我需要部署一個自己多年前寫的項目。由于時間緊、任務重&#xff0c;我懶得去升級到8.0了。于是計劃在Ubuntu20.04上安裝.NET Core3.1項目。可以使用包管理器卻安裝不上了。于是&#xff0c;我就嘗試二進制文件安裝。 實際上二進…

【python基礎知識】Day 27 函數專題2:裝飾器

知識點&#xff1a; 裝飾器的思想&#xff1a;進一步復用函數的裝飾器寫法注意內部函數的返回值 裝飾器教程 作業&#xff1a; 編寫一個裝飾器 logger&#xff0c;在函數執行前后打印日志信息&#xff08;如函數名、參數、返回值&#xff09; def logger(func):def wrapper(*ar…

MGX:多智能體管理開發流程

MGX的多智能體團隊如何通過專家混合系統采用全新方法,徹底改變開發流程,與當前的單一智能體工具截然不同。 Lovable和Cursor在自動化我們的特定開發流程方面取得了巨大飛躍,但問題是它們僅解決軟件開發的單一領域。 這就是MGX(MetaGPT X)的用武之地,它是一種正在重新定…

【未完】【GNN筆記】EvolveGCN:Evolving Graph Convolutional Networks for Dynamics Graphs

Evolving Graph Convolutional Networks for Dynamics Graphs 視頻鏈接&#xff1a;《圖神經網絡》 相關系列&#xff1a; 《Dynamic Graph的分類》《動態圖網絡之Dynamic Self-Attention Network》 文章目錄 Evolving Graph Convolutional Networks for Dynamics Graphs一、…

Go語言之路————并發

Go語言之路————并發 前言協程管道SelectsyncWaitGroup鎖 前言 我是一名多年Java開發人員&#xff0c;因為工作需要現在要學習go語言&#xff0c;Go語言之路是一個系列&#xff0c;記錄著我從0開始接觸Go&#xff0c;到后面能正常完成工作上的業務開發的過程&#xff0c;如…

Gmsh劃分網格|四點矩形

先看下面這段官方自帶腳本 /*********************************************************************** Gmsh tutorial 1** Variables, elementary entities (points, curves, surfaces), physical* entities (points, curves, surfaces)********************************…

leetcode0215. 數組中的第K個最大元素-medium

1 題目&#xff1a;數組中的第K個最大元素 官方標定難度&#xff1a;中 給定整數數組 nums 和整數 k&#xff0c;請返回數組中第 k 個最大的元素。 請注意&#xff0c;你需要找的是數組排序后的第 k 個最大的元素&#xff0c;而不是第 k 個不同的元素。 你必須設計并實現時…

rocketmq 環境配置[python]

因本人是 python 開發&#xff0c;macbook 開發。windows 可以采取配置遠程 linux 解釋器或者 pycharm 專業版的 docker 解釋器進行開發 M1 芯片 本地運行 rocketmq rocketmq Python 開源地址&#xff1a; https://github.com/apache/rocketmq-client-python 因為需要 linu…

OCCT知識筆記之OCAF框架詳解

OCAF框架在OCCT項目中的構建與使用指南 Open CASCADE Application Framework (OCAF)是Open CASCADE Technology (OCCT)中用于管理CAD數據的核心框架&#xff0c;它提供了一種結構化方式來組織和管理復雜的CAD數據&#xff0c;如裝配體、形狀、屬性(顏色、材料)和元數據等。本文…

go-數據庫基本操作

1. 配置數據庫 package mainimport ("gorm.io/driver/mysql""gorm.io/gorm" ) #配置表結構 type User struct {ID int64 json:"id" gorm:"primary_key" // 主鍵ID自增長Username stringPassword string } #配置連接接信息 func…