圖片強度轉換主要用於調整影像的亮度和對比度,以便加強影像中的特徵或提升影像的可視性。這種轉換通常透過調整像素的亮度值和對比度來實現,從而使影像呈現出更合適的視覺效果。這種處理方法在許多影像處理應用中都非常常見,例如在調整曝光、增強細節等方面。
負片轉換用於將一張彩色或灰度影像的顏色或亮度值取反,從而產生一個負片效果。負片轉換的原理非常簡單,它基本上是將每個像素的亮度值反向,以產生新的像素值。對於灰度影像,取反的方法是將最大亮度值(255)減去每個像素的亮度值。負片轉換的公式可以表示為:
這張Lenna圖就是經過負片轉換以後的結果,如果你再對這張照片進行負片轉換,就會變為原先的Lenna圖。
伽馬校正是一種調整影像亮度和對比度的校正法,用於修正螢幕、相機和影像處理中的非線性亮度響應。它的主要目的是使影像在不同的輸出設備上以及不同的環境中都能夠呈現出更自然、更平衡的視覺效果。伽馬校正的核心概念基於人類眼睛對亮度變化的非線性感知。人眼對亮度的感知不是線性的,而是呈現出一種對低亮度變化敏感,對高亮度變化不敏感的特性。因此,在數位影像中,為了使影像在顯示器上以及人眼中看起來更加平衡,需要對亮度值進行調整。
伽馬校正的數學公式可以表示為:
下圖是圖片在經過不同的γ值校正後所產生的結果。
下圖是伽馬校正的輸入-輸出關係曲線圖,透過調整γ值可以得到不同的關係曲線,從而影響亮度值的映射方式。
二值化是一種影像處理技術,用於將一張灰度影像轉換為只有兩個值的影像,黑色和白色。這種處理可以簡化影像,強調重要特徵,並減少計算成本。
二值化的原理是基於閾值的概念。閾值是一個用來劃分灰度值的數值,根據閾值,影像中的每個像素點將被分為兩個類別:高於閾值的像素被賦予一個值(白色),低於閾值的像素被賦予另一個值(黑色),形成了一個只包含兩種顏色的影像。
這個程式碼提供了兩種強度轉換的運算方式,一個是使用OpenCV內建的函式,另一個是使用蜂巢迴圈實現的演算法,兩者效果一樣。你可以透過設定USE_OPENCV
成1
或0
來決定你要使用前者還是後者的實現方式。
#define USE_OPENCV 1
負片轉換最簡單,直接將255減原始圖就是負片轉換的結果。
cv::imshow("Nagative Transformation", 255 - grayImage);
cv::intensity_transform::gammaCorrection(grayImage, dst, gamma);
grayImage
:原始灰階影像。dst
:用於儲存伽馬校正後的結果的影像。gamma
:伽馬值,決定了伽馬曲線的形狀,影響校正的效果。伽馬值越大,影像的暗部和亮部的對比度會增強。cv::threshold
,用於執行閾值二值化操作。它需要幾個參數:
cv::threshold(grayImage, binaryImage, thresholdValue, 255, CV_8UC1);
grayImage
:原始灰階影像。binaryImage
:用於儲存二值化後的結果的影像。thresholdValue
:閾值,決定了像素的分類,小於閾值的像素被設置為0,大於等於閾值的像素被設置為255。255
:表示二值化後的像素值,一般用於將像素值設置為最大值,即白色。CV_8UC1
:表示輸出影像的數據類型,這裡是8位無符號整數,單通道。cv::Mat
物件 dst
來儲存伽馬校正後的影像。gamma
的不同,使用 std::pow
函數計算正規化值的指數運算,得到調整後的像素值。dst
影像的對應位置。這樣,程式碼通過遍歷每個像素,對每個像素的灰階值進行伽馬校正的計算,最終生成了一張具有調整亮度的新灰階影像。
cv::Mat dst;
// 自行計算伽馬校正
dst = cv::Mat::zeros(grayImage.rows, grayImage.cols, CV_8UC1);
for (int y = 0; y < grayImage.rows; y++)
{
for (int x = 0; x < grayImage.cols; x++)
{
uchar value = grayImage.at<uchar>(y, x);
float input = value / 255.0f;
dst.at<uchar>(y, x) = (uchar)255 * std::pow(input, gamma);
}
}
cv::Mat
物件 binaryImage
,用於存儲二值化後的影像。cv::Mat::zeros
建立一個全黑的單通道灰階影像,大小與原始灰階影像相同。thresholdValue
,則將 binaryImage
中相應位置的像素值設置為255,表示目標物體。否則,保持該像素值為0,表示背景。double thresholdValue = position;
cv::Mat binaryImage;
binaryImage = cv::Mat::zeros(grayImage.rows, grayImage.cols, CV_8UC1);
for (int y = 0; y < grayImage.rows; y++)
{
for (int x = 0; x < grayImage.cols; x++)
{
uchar value = grayImage.at<uchar>(y, x);
if (value >= thresholdValue)
{
binaryImage.at<uchar>(y, x) = 255;
}
}
}
LOG_LEVEL_SILENT
,禁止OpenCV輸出日誌訊息。#include <iostream>
#include "opencv2/opencv.hpp"
#include "math.h"
#include "opencv2/intensity_transform.hpp"
#include "opencv2/core/utils/logger.hpp"
#define USE_OPENCV 1
using namespace std;
// 設置滑動條的回調函數
void trackbar_thresholding_callback(int position, void*);
void trackbar_gamma_correction_callback(int position, void*);
cv::Mat grayImage;
int main()
{
cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_SILENT);
// 讀取影像
grayImage = cv::imread("C:\\Users\\vince\\Downloads\\Lenna.png", cv::IMREAD_GRAYSCALE);
// 建立二值化影像視窗和滑動條
cv::namedWindow("Binary Image", cv::WindowFlags::WINDOW_NORMAL);
cv::resizeWindow("Binary Image", 512.0f * ((float)grayImage.cols / grayImage.rows), 512);
cv::createTrackbar("Threshold", "Binary Image", NULL, 255, trackbar_thresholding_callback);
cv::imshow("Binary Image", grayImage);
// 建立Gamma校正視窗和滑動條
cv::namedWindow("Gamma Correction", cv::WindowFlags::WINDOW_NORMAL);
cv::resizeWindow("Gamma Correction", 512.0f * ((float)grayImage.cols / grayImage.rows), 512);
cv::createTrackbar("Gamma", "Gamma Correction", NULL, 100, trackbar_gamma_correction_callback);
cv::imshow("Gamma Correction", grayImage);
// 顯示底片影像
cv::imshow("Negative Transformation", 255 - grayImage);
cv::waitKey(0);
return 0;
}
// Gamma校正的滑動條回調函數
void trackbar_gamma_correction_callback(int position, void*)
{
double gamma = position / 10.0;
cv::Mat dst;
#if USE_OPENCV
cv::intensity_transform::gammaCorrection(grayImage, dst, gamma);
#else
dst = cv::Mat::zeros(grayImage.rows, grayImage.cols, CV_8UC1);
for (int y = 0; y < grayImage.rows; y++)
{
for (int x = 0; x < grayImage.cols; x++)
{
uchar value = grayImage.at<uchar>(y, x);
float input = value / 255.0f;
dst.at<uchar>(y, x) = (uchar)255 * std::pow(input, gamma);
}
}
#endif
cv::imshow("Gamma Correction", dst);
}
// 二值化的滑動條回調函數
void trackbar_thresholding_callback(int position, void*)
{
double thresholdValue = position;
cv::Mat binaryImage;
#if USE_OPENCV
cv::threshold(grayImage, binaryImage, thresholdValue, 255, CV_8UC1);
#else
binaryImage = cv::Mat::zeros(grayImage.rows, grayImage.cols, CV_8UC1);
for (int y = 0; y < grayImage.rows; y++)
{
for (int x = 0; x < grayImage.cols; x++)
{
uchar value = grayImage.at<uchar>(y, x);
if (value >= thresholdValue)
{
binaryImage.at<uchar>(y, x) = 255;
}
}
}
#endif
cv::imshow("Binary Image", binaryImage);
}