一、前言
在當(dāng)代數(shù)字化轉(zhuǎn)型的浪潮中,計(jì)算機(jī)視覺技術(shù)無疑占據(jù)了舉足輕重的地位,其應(yīng)用范圍之廣,影響力之深,已成為推動(dòng)社會(huì)進(jìn)步的關(guān)鍵力量之一。而OpenCV,作為計(jì)算機(jī)視覺領(lǐng)域的佼佼者,憑借其卓越的性能與廣泛的兼容性,為開發(fā)者提供了強(qiáng)大的工具集,助力其實(shí)現(xiàn)復(fù)雜視覺任務(wù)的高效處理。
環(huán)境亮度識(shí)別,實(shí)質(zhì)上是一項(xiàng)要求計(jì)算機(jī)系統(tǒng)能夠精準(zhǔn)分析并量化圖像中光照強(qiáng)度的技術(shù)。要求計(jì)算機(jī)能夠理解并量化人類視覺系統(tǒng)對(duì)光線變化的感知,進(jìn)而做出相應(yīng)的判斷和反應(yīng)。無論是智能照明系統(tǒng)中的自動(dòng)調(diào)光,還是自動(dòng)駕駛汽車在復(fù)雜光照條件下的安全導(dǎo)航,亦或是安防監(jiān)控中對(duì)異常光源的即時(shí)警報(bào),這一技術(shù)都扮演著至關(guān)重要的角色。它不僅提高了自動(dòng)化系統(tǒng)的效率和可靠性,還極大地豐富了人機(jī)交互的方式,讓機(jī)器能夠更加“善解人意”。
例如,在智能家居系統(tǒng)中,自動(dòng)調(diào)節(jié)室內(nèi)光線以適應(yīng)不同的活動(dòng)需求或節(jié)能目的;在智能交通系統(tǒng)中,動(dòng)態(tài)調(diào)整道路照明以應(yīng)對(duì)天氣變化和車流量波動(dòng);在增強(qiáng)現(xiàn)實(shí)領(lǐng)域,實(shí)時(shí)調(diào)整虛擬內(nèi)容的顯示效果以匹配真實(shí)世界的光照條件,這些都是環(huán)境亮度識(shí)別技術(shù)需要用到的地方。。
OpenCV,作為一款開源的計(jì)算機(jī)視覺庫,因其強(qiáng)大的功能和廣泛的適用性,成為了實(shí)現(xiàn)環(huán)境亮度識(shí)別的理想工具。OpenCV不僅提供了豐富的圖像處理函數(shù),還支持多種圖像分析算法,這使得開發(fā)者能夠輕松地從圖像中提取亮度信息,并將其轉(zhuǎn)化為可操作的數(shù)據(jù)。通過加載一張圖片,利用OpenCV的圖像處理能力,可以計(jì)算出圖片中亮度的分布情況,進(jìn)而得到一個(gè)反映環(huán)境亮度水平的百分比值。
本文章介紹如何利用OpenCV加載一張圖片,運(yùn)用OpenCV庫內(nèi)置的圖像處理技術(shù),識(shí)別并計(jì)算圖片中的亮度百分比。
二、OpenCV開發(fā)環(huán)境安裝
【1】OpenCV庫下載(官網(wǎng))
OpenCV是開源的計(jì)算機(jī)視覺、機(jī)器學(xué)習(xí)軟件庫,其圖片處理的功能非常強(qiáng)大,并且速度很快。 作為目標(biāo)檢測(cè)功能,OpenCV里本身就自帶了很多的模型,比如: 人眼檢測(cè)、鼻子檢測(cè)、嘴巴檢測(cè)、人臉檢測(cè)、人體檢測(cè)、貓臉檢測(cè)等等,下載完OpenCV,就能直接進(jìn)行圖像識(shí)別測(cè)試體驗(yàn),并且OpenCV也可以直接調(diào)用YOLO的模型,精確識(shí)別各種物體,yolo v3 里自帶的模型文件可以精確識(shí)別常見的很多物體: 比如: 狗、汽車、自行車、人體、書本、手機(jī)等等。
OpenCV下載地址:https://opencv.org/releases/page/3/
目前最新的版本是4.3,那么就下載最新的版本。
下載下來是一個(gè)exe文件,雙擊就可以安裝,實(shí)際就是解壓,可以選擇解壓的路徑,解壓出來的文件包含源文件、庫文件一大堆,比較大,可以直接放在一個(gè)固定的目錄,后面程序里直接填路徑來調(diào)用即可。 這個(gè)下載下來的庫文件里只包含了X64的庫,適用于MSVS 64位編譯器。
解壓完成。
解壓后在build目錄下看到有VC14和VC15的目錄。這表示什么含義呢?
OpenCV VC14和VC15的區(qū)別在于它們所使用的編譯器版本不同。VC14使用的是Visual Studio 2015的編譯器,而VC15使用的是Visual Studio 2017的編譯器。這意味著VC15可以利用更先進(jìn)的編譯器技術(shù),從而提高代碼的性能和效率。此外,VC15還支持更多的C++11和C++14特性,使得開發(fā)更加方便和靈活。
解釋說明:
VC11,Visual Studio 2012編譯器
VC14,Visual Studio 2015編譯器
VC15,Visual Studio 2017編譯器
- VC11構(gòu)建需要安裝Visual Studio 2012 x86或x64的Visual C ++ Redistributable
- VC14構(gòu)建需要安裝Visual Studio 2015 x86或x64的Visual C ++ Redistributable
- VC15構(gòu)建需要安裝Visual Studio 2017 x64或x86的Visual C ++ Redistributable
在bin
目錄下的運(yùn)行庫需要拷貝到生成的應(yīng)用程序目錄下。
【2】MinGw編譯器
如果想要使用MinGw編譯器編譯,可以從這里 https://github.com/huihut/OpenCV-MinGW-Build 下載對(duì)應(yīng)的OpenCV庫進(jìn)行使用。
GitHub的地址在CodeChina有鏡像,可以從這里去下載,速度比較快:gitcode.net/mirrors/hui…
打開鏈接后,自己去選擇適合自己編譯器的版本,我的MinGW是730剛好就使用下面這個(gè)版本。
下面分別介紹VS2017 64位編譯器和MinGW 32位編譯器如何引用OpenCV的庫。
(1)MSVC 64位編譯器–QT的xx.pro工程文件里的寫法
INCLUDEPATH += C:/opencv/build/include
INCLUDEPATH += C:/opencv/build/include/opencv
INCLUDEPATH += C:/opencv/build/include/opencv2
LIBS += -LC:/opencv/build/x64/vc14/lib
-lopencv_world347d
LIBS += -LC:/opencv/build/x64/vc14/lib
-lopencv_world347
(2)MinGW 32位編譯器–QT的xx.pro工程文件里的寫法
INCLUDEPATH+=C:/OpenCV-MinGW-Build-OpenCV-3.4.7/include
C:/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv
C:/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv2
LIBS+=C:/OpenCV-MinGW-Build-OpenCV-3.4.7/x86/mingw/bin/libopencv_*.dll
工程編程成功之后,需要將OpenCV對(duì)應(yīng)的dll文件拷貝到exe同級(jí)目錄,否則運(yùn)行時(shí)找不到dll會(huì)導(dǎo)致程序異常結(jié)束。 這些dll文件就是在OpenCV的bin目錄下。
OpenCV自帶的模型文件在 C:opencvsourcesdatahaarcascades_cuda
這個(gè)目錄下。
這個(gè)就是人臉檢測(cè)模型文件:
三、實(shí)現(xiàn)代碼
3.1 識(shí)別亮度(C++)
開發(fā)環(huán)境:在Windows下安裝一個(gè)VS即可。我當(dāng)前采用的版本是VS2020。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// 計(jì)算亮度百分比的函數(shù)
double calculateBrightnessPercentage(Mat image) {
// 將圖像轉(zhuǎn)換為灰度圖
Mat grayImage;
cvtColor(image, grayImage, COLOR_BGR2GRAY);
// 計(jì)算總像素?cái)?shù)
int totalPixels = grayImage.rows * grayImage.cols;
// 計(jì)算亮度較高的像素?cái)?shù)(假設(shè)亮度閾值為200)
int brightPixels = 0;
for (int i = 0; i < grayImage.rows; ++i) {
for (int j = 0; j < grayImage.cols; ++j) {
if (grayImage.at<uchar>(i, j) > 200) { // 可根據(jù)需要調(diào)整閾值
brightPixels++;
}
}
}
// 計(jì)算亮度百分比
double percentage = (static_cast<double>(brightPixels) / totalPixels) * 100.0;
return percentage;
}
int main() {
// 加載圖像
Mat image = imread("path_to_your_image.jpg");
if (image.empty()) {
cout << "無法打開或找到圖像" << endl;
return -1;
}
// 計(jì)算亮度百分比
double brightnessPercentage = calculateBrightnessPercentage(image);
// 輸出亮度百分比
cout << "亮度百分比: " << brightnessPercentage << "%" << endl;
return 0;
}
(1)頭文件和命名空間:包括必要的OpenCV頭文件 (opencv2/opencv.hpp
),使用 cv
和 std
命名空間以便于調(diào)用。
(2)calculateBrightnessPercentage
函數(shù):
- 使用
cvtColor
將輸入圖像轉(zhuǎn)換為灰度圖。 - 計(jì)算圖像中總像素?cái)?shù)。
- 統(tǒng)計(jì)像素灰度值高于設(shè)定閾值(本例中為200)的像素?cái)?shù)。
- 計(jì)算亮度百分比,即高亮像素?cái)?shù)占總像素?cái)?shù)的百分比。
(3)main
函數(shù):
- 使用
imread
從指定路徑加載圖像。 - 檢查圖像是否成功加載。
- 調(diào)用
calculateBrightnessPercentage
函數(shù)計(jì)算圖像的亮度百分比。 - 輸出計(jì)算得到的亮度百分比。
3.2 識(shí)別亮度(Python)
以下是使用Python和OpenCV計(jì)算圖像亮度百分比的代碼示例:
import cv2
import numpy as np
# 計(jì)算亮度百分比的函數(shù)
def calculate_brightness_percentage(image):
# 轉(zhuǎn)換為灰度圖像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 計(jì)算總像素?cái)?shù)
total_pixels = gray_image.shape[0] * gray_image.shape[1]
# 計(jì)算亮度較高的像素?cái)?shù)(假設(shè)亮度閾值為200)
bright_pixels = np.sum(gray_image > 200) # 可根據(jù)需要調(diào)整閾值
# 計(jì)算亮度百分比
percentage = (bright_pixels / total_pixels) * 100.0
return percentage
def main():
# 加載圖像
image = cv2.imread('path_to_your_image.jpg')
if image is None:
print("無法打開或找到圖像")
return
# 計(jì)算亮度百分比
brightness_percentage = calculate_brightness_percentage(image)
# 輸出亮度百分比
print(f"亮度百分比: {brightness_percentage}%")
if __name__ == "__main__":
main()
(1)函數(shù) calculate_brightness_percentage
:
- 使用
cv2.cvtColor
將輸入圖像轉(zhuǎn)換為灰度圖。 - 計(jì)算圖像中總像素?cái)?shù)。
- 使用 NumPy 條件判斷
gray_image > 200
來統(tǒng)計(jì)亮度較高的像素?cái)?shù)(可以根據(jù)需要調(diào)整閾值200
)。 - 計(jì)算亮度百分比,即高亮像素?cái)?shù)占總像素?cái)?shù)的百分比。
(2)main
函數(shù):
- 使用
cv2.imread
從指定路徑加載圖像。 - 檢查圖像是否成功加載。
- 調(diào)用
calculate_brightness_percentage
函數(shù)計(jì)算圖像的亮度百分比。 - 輸出計(jì)算得到的亮度百分比。
3.3 顏色分類識(shí)別(C++)
開發(fā)環(huán)境:在Windows下安裝一個(gè)VS即可。我當(dāng)前采用的版本是VS2020。
下面是使用OpenCV(C++)加載一張圖片,并識(shí)別出黑、白、紅、橙、黃、綠、青、藍(lán)、紫等顏色的占比的完整代碼示例:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// 定義顏色的閾值范圍(HSV顏色空間)
const int MIN_H_RED = 0;
const int MAX_H_RED = 10;
const int MIN_H_ORANGE = 11;
const int MAX_H_ORANGE = 25;
const int MIN_H_YELLOW = 26;
const int MAX_H_YELLOW = 34;
const int MIN_H_GREEN = 35;
const int MAX_H_GREEN = 85;
const int MIN_H_CYAN = 86;
const int MAX_H_CYAN = 105;
const int MIN_H_BLUE = 106;
const int MAX_H_BLUE = 130;
const int MIN_H_PURPLE = 131;
const int MAX_H_PURPLE = 160;
// 計(jì)算顏色比例的函數(shù)
void calculate_color_percentages(Mat image) {
Mat hsvImage;
cvtColor(image, hsvImage, COLOR_BGR2HSV);
// 初始化顏色像素統(tǒng)計(jì)變量
int totalPixels = hsvImage.rows * hsvImage.cols;
int blackPixels = 0, whitePixels = 0;
int redPixels = 0, orangePixels = 0, yellowPixels = 0;
int greenPixels = 0, cyanPixels = 0, bluePixels = 0, purplePixels = 0;
// 遍歷圖像像素
for (int i = 0; i < hsvImage.rows; ++i) {
for (int j = 0; j < hsvImage.cols; ++j) {
Vec3b pixel = hsvImage.at<Vec3b>(i, j);
int hue = pixel[0]; // 色調(diào)
// 根據(jù)色調(diào)范圍判斷顏色
if (hue >= MIN_H_RED && hue <= MAX_H_RED) {
redPixels++;
} else if (hue >= MIN_H_ORANGE && hue <= MAX_H_ORANGE) {
orangePixels++;
} else if (hue >= MIN_H_YELLOW && hue <= MAX_H_YELLOW) {
yellowPixels++;
} else if (hue >= MIN_H_GREEN && hue <= MAX_H_GREEN) {
greenPixels++;
} else if (hue >= MIN_H_CYAN && hue <= MAX_H_CYAN) {
cyanPixels++;
} else if (hue >= MIN_H_BLUE && hue <= MAX_H_BLUE) {
bluePixels++;
} else if ((hue >= 0 && hue < MIN_H_RED) || (hue > MAX_H_PURPLE && hue <= 179)) {
purplePixels++;
}
}
}
// 計(jì)算顏色百分比
double percentageBlack = (static_cast<double>(blackPixels) / totalPixels) * 100.0;
double percentageWhite = (static_cast<double>(whitePixels) / totalPixels) * 100.0;
double percentageRed = (static_cast<double>(redPixels) / totalPixels) * 100.0;
double percentageOrange = (static_cast<double>(orangePixels) / totalPixels) * 100.0;
double percentageYellow = (static_cast<double>(yellowPixels) / totalPixels) * 100.0;
double percentageGreen = (static_cast<double>(greenPixels) / totalPixels) * 100.0;
double percentageCyan = (static_cast<double>(cyanPixels) / totalPixels) * 100.0;
double percentageBlue = (static_cast<double>(bluePixels) / totalPixels) * 100.0;
double percentagePurple = (static_cast<double>(purplePixels) / totalPixels) * 100.0;
// 輸出顏色百分比
cout << "黑色百分比: " << percentageBlack << "%" << endl;
cout << "白色百分比: " << percentageWhite << "%" << endl;
cout << "紅色百分比: " << percentageRed << "%" << endl;
cout << "橙色百分比: " << percentageOrange << "%" << endl;
cout << "黃色百分比: " << percentageYellow << "%" << endl;
cout << "綠色百分比: " << percentageGreen << "%" << endl;
cout << "青色百分比: " << percentageCyan << "%" << endl;
cout << "藍(lán)色百分比: " << percentageBlue << "%" << endl;
cout << "紫色百分比: " << percentagePurple << "%" << endl;
}
int main() {
// 加載圖像
Mat image = imread("path_to_your_image.jpg");
if (image.empty()) {
cout << "無法打開或找到圖像" << endl;
return -1;
}
// 計(jì)算顏色比例
calculate_color_percentages(image);
return 0;
}
3.4 顏色分類識(shí)別(python)
以下是相應(yīng)的Python版本代碼,用于加載圖像并計(jì)算黑、白、紅、橙、黃、綠、青、藍(lán)、紫顏色的占比:
import cv2
import numpy as np
# 定義顏色的閾值范圍(HSV顏色空間)
COLOR_THRESHOLDS = {
'black': ([0, 0, 0], [180, 255, 30]), # 黑色
'white': ([0, 0, 231], [180, 18, 255]), # 白色
'red': ([0, 43, 46], [10, 255, 255]), # 紅色
'orange': ([11, 43, 46], [25, 255, 255]), # 橙色
'yellow': ([26, 43, 46], [34, 255, 255]), # 黃色
'green': ([35, 43, 46], [85, 255, 255]), # 綠色
'cyan': ([86, 43, 46], [105, 255, 255]), # 青色
'blue': ([106, 43, 46], [130, 255, 255]), # 藍(lán)色
'purple': ([131, 43, 46], [160, 255, 255]) # 紫色
}
# 計(jì)算顏色比例的函數(shù)
def calculate_color_percentages(image):
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 初始化顏色像素統(tǒng)計(jì)變量
total_pixels = hsv_image.shape[0] * hsv_image.shape[1]
color_percentages = {}
# 遍歷顏色閾值范圍
for color_name, (lower, upper) in COLOR_THRESHOLDS.items():
lower_np = np.array(lower, dtype=np.uint8)
upper_np = np.array(upper, dtype=np.uint8)
# 根據(jù)顏色閾值創(chuàng)建掩碼
mask = cv2.inRange(hsv_image, lower_np, upper_np)
# 計(jì)算掩碼中白色像素的數(shù)量
num_pixels = cv2.countNonZero(mask)
# 計(jì)算百分比
percentage = (num_pixels / total_pixels) * 100.0
color_percentages[color_name] = percentage
return color_percentages
if __name__ == "__main__":
# 加載圖像
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)
if image is None:
print(f"無法打開或找到圖像:{image_path}")
else:
# 計(jì)算顏色比例
percentages = calculate_color_percentages(image)
# 輸出顏色百分比
for color, percentage in percentages.items():
print(f"{color}百分比: {percentage:.2f}%")
(1)顏色定義和閾值范圍:
- 使用HSV顏色空間來識(shí)別顏色,定義了各種顏色的HSV閾值范圍。
- 每個(gè)顏色都有一個(gè)對(duì)應(yīng)的最小和最大HSV值。
(2)calculate_color_percentages
函數(shù):
- 使用
cv2.cvtColor
將圖像從BGR色彩空間轉(zhuǎn)換為HSV色彩空間。 - 初始化顏色百分比的字典。
- 針對(duì)每種顏色的HSV閾值范圍,使用
cv2.inRange
創(chuàng)建顏色掩碼。 - 使用
cv2.countNonZero
計(jì)算掩碼中非零像素的數(shù)量,即符合顏色條件的像素?cái)?shù)量。 - 計(jì)算每種顏色在圖像中的百分比。
(3)main
函數(shù):
- 加載指定路徑的圖像。
- 檢查圖像是否成功加載。
- 調(diào)用
calculate_color_percentages
函數(shù)計(jì)算并輸出圖像中各種顏色的百分比。