opencv--day02--圖像顏色處理及圖像仿射變換

文章目錄

  • 前言
  • 一、 圖像顏色處理
    • 1. 顏色加法
      • 1.1 OpenCV加法
      • 1.2 numpy加法
      • 1.3 顏色加權加法
    • 2.顏色空間
      • 2.1 RGB顏色空間
      • 2.2 HSV顏色空間
    • 3. 顏色轉換
      • 3.1 讀取的圖片同時轉換
      • 3.2 對已有圖片轉換
    • 4. 圖像灰度化
      • 4.1 灰度圖概念
      • 4.2 最大值灰度化
      • 4.3 平均值灰度化
      • 4.4 加權均值灰度化
    • 5. 圖像二值化處理
      • 5.1 二值圖像
      • 5.2 閾值法(THRESH_BINARY)
      • 5.3 反閾值法(THRESH_BINARY_INV)
      • 5.4 截斷閾值法(THRESH_TRUNC)
      • 5.5 低閾值零處理(THRESH_TOZERO)
      • 5.6 超閾值零處理(THRESH_TOZERO_INV)
      • 5.7 OTSU閾值法
      • 5.8 自適應二值化
        • 5.8.1 取均值
        • 5.8.2 加權求和(高斯法)
  • 二、圖像仿射變換
    • 1. 圖像翻轉(圖像鏡像旋轉)
    • 2.仿射變換
      • 2.1 仿射變換的基本原理 -- 單點旋轉
      • 2.2 仿射變換函數
  • 總結
  • --- opencv系列相關文章 ---


前言

昨天我們初步了解了opencv-python,學習了利用cv2的相關API對已知路徑下的圖片進行文件基本操作,最后還完成了對視頻的操作。今天我們要學習圖像顏色處理及圖像仿射變換。


一、 圖像顏色處理

1. 顏色加法

1.1 OpenCV加法

  • opencv加法是飽和操作
    • 飽和的意思是若計算的結果超出當前上限,就以當前上限值作為最終結果。
  • 在opencv中,顏色值默認是np.unit8類型,上限為255

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像cao = cv.imread('../images/cao.png')pig = cv.imread('../images/pig.png')# 飽和操作 -- 范圍是np.uint8, 超出上限的取255dst1 = cv.add(cao, pig)print(cao[500,500,:])print(pig[500,500,:])print('cv飽和運算\n',dst1[500,500,:])cv.imshow('dst1', dst1)# 設定顯示等待cv.waitKey(0)# 釋放內存cv.destroyAllWindows()

1.2 numpy加法

  • 利用numpy加法的前提是進行加法運算的兩張圖片的形狀大小要一樣
  • numpy加法是模運算
    • 取模意思是用計算結果對255取模

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像cao = cv.imread('../images/cao.png')pig = cv.imread('../images/pig.png')# 飽和操作 -- 范圍是np.uint8, 超出上限的取255dst2 = cao + pigprint(cao[500,500,:])print(pig[500,500,:])print('numpy取模運算\n',dst2[500,500,:])cv.imshow('dst1', dst2)# 設定顯示等待cv.waitKey(0)# 釋放內存cv.destroyAllWindows()

1.3 顏色加權加法

同樣滿足飽和運算

基本格式:

cv2.addWeighted(src1,alpha,src2,deta,gamma)

參數說明:

  • src1src2:輸入圖像。
  • alphabeta:兩張圖象權重。
  • gamma:亮度調整值。
    • gamma > 0,圖像會變亮。
    • gamma < 0,圖像會變暗。
    • gamma = 0,則沒有額外的亮度調整。

示例

import cv2 as cv
# import numpy as np
if __name__ == '__main__':# 讀圖cao = cv.imread('../images/cao.png')pig = cv.imread('../images/pig.png')# cv2.addWeighted(src1,alpha,src2,deta,gamma) dst3 = cv.addWeighted(cao,0.3,pig,0.7,100)print(cao[500,500,:])print(pig[500,500,:])print('cv加權運算\n',dst3[500,500,:])# 顯示圖片cv.imshow('dst3',dst3)cv.waitKey(0)# 釋放內存cv.destroyAllWindows()

2.顏色空間

2.1 RGB顏色空間

在圖像處理中,最常見的就是RGB顏色空間。RGB顏色空間是我們接觸最多的顏色空間,是一種用于表示和顯示彩色圖像的一種顏色模型。RGB代表紅色(Red)綠色(Green)藍色(Blue),這三種顏色通過不同強度的光的組合來創建其他顏色,廣泛應用于我們的生活中,比如電視、電腦顯示屏以及上面實驗中所介紹的RGB彩色圖。

RGB顏色模型基于笛卡爾坐標系,如下圖所示,RGB原色值位于3個角上,二次色青色、紅色和黃色位于另外三個角上,黑色位于原點處,白色位于離原點最遠的角上。因為黑色在RGB三通道中表現為(0,0,0),所以映射到這里就是原點;而白色是(255,255,255),所以映射到這里就是三個坐標為最大值的點。
RGB顏色空間
RGB顏色空間可以產生大約1600萬(2553255^32553)種顏色,幾乎包括了世界上的所有顏色,也就是說可以使用RGB顏色空間來生成任意一種顏色。

注意:
在OpenCV中,顏色是以BGR的方式進行存儲的,而不是RGB,這也是上面紅色的像素值是(0,0,255)而不是(255,0,0)的原因。

2.2 HSV顏色空間

HSV顏色空間指的是HSV顏色模型,這是一種與RGB顏色模型并列的顏色空間表示法。RGB顏色模型使用紅、綠、藍三原色的強度來表示顏色,是一種加色法模型,即顏色的混合是添加三原色的強度。而HSV顏色空間使用色調(Hue)飽和度(Saturation)亮度(Value)三個參數來表示顏色,色調H表示顏色的種類,如紅色、綠色、藍色等;飽和度表示顏色的純度或強度,如紅色越純,飽和度就越高;亮度表示顏色的明暗程度,如黑色比白色亮度低。

HSV顏色模型是一種六角錐體模型,如下圖所示:
HSV

色調H:

使用角度度量,取值范圍為0°~360°,從紅色開始按逆時針方向計算,紅色為0°,綠色為120°,藍色為240°。它們的補色是:黃色為60°,青色為180°,紫色為300°。通過改變H的值,可以選擇不同的顏色

飽和度S:

飽和度S表示顏色接近光譜色的程度。一種顏色可以看成是某種光譜色與白色混合的結果。其中光譜色所占的比例越大,顏色接近光譜色的程度就越高,顏色的飽和度就越高。飽和度越高,顏色就越深而艷,光譜色的白光成分為0,飽和度達到最高。通常取值范圍為0%~100%,其中0%表示灰色或無色,100%表示純色,通過調整飽和度的值,可以使顏色變得更加鮮艷或者更加灰暗。

明度V:

明度表示顏色明亮的程度,對于光源色,明度值與發光體的光亮度有關;對于物體色,此值和物體的透射比或反射比有關。通常取值范圍為0%(黑)到100%(白),通過調整明度的值,可以使顏色變得更亮或者更暗。

一般對顏色空間的圖像進行有效處理都是在HSV空間進行的,然后對于基本色中對應的HSV分量需要給定一個嚴格的范圍,下面是通過實驗計算的模糊范圍(準確的范圍在網上都沒有給出)。

H: 0— 180

S: 0— 255

V: 0— 255

此處把部分紅色歸為紫色范圍:

模糊范圍

為什么有了RGB顏色空間我們還是需要轉換成HSV顏色空間來進行圖像處理呢?

  • 符合人類對顏色的感知方式:人類對顏色的感知是基于色調、飽和度和亮度三個維度的,而HSV顏色空間恰好就是通過這三個維度來描述顏色的。因此,使用HSV空間處理圖像可以更直觀地調整顏色和進行色彩平衡等操作,更符合人類的感知習慣。
  • 顏色調整更加直觀:在HSV顏色空間中,色調、飽和度和亮度的調整都是直觀的,而在RGB顏色空間中調整顏色不那么直觀。例如,在RGB空間中要調整紅色系的顏色,需要同時調整R、G、B三個通道的數值,而在HSV空間中只需要調整色調和飽和度即可。
  • 降維處理有利于計算:在圖像處理中,降維處理可以減少計算的復雜性和計算量。HSV顏色空間相對于RGB顏色空間,減少了兩個維度(紅、綠、藍),這有利于進行一些計算和處理任務,比如色彩分割、匹配等。

因此,在進行圖片顏色識別時,我們會將RGB圖像轉換到HSV顏色空間,然后根據顏色區間來識別目標顏色。

3. 顏色轉換

3.1 讀取的圖片同時轉換

基本格式:

cv2.imread(path  [,讀取方式])

參數說明:
昨天我們講了path,而讀取方式有很多種,默認是BGR形式

常見 mode 參數對照表:

模式值(flag)常量名功能說明
1cv2.IMREAD_COLOR(默認)以彩色方式讀取圖像,忽略透明通道
0cv2.IMREAD_GRAYSCALE以灰度模式讀取圖像(單通道)
-1cv2.IMREAD_UNCHANGED以原始方式讀取圖像,保留 alpha 通道
2cv2.IMREAD_ANYDEPTH若圖像是 16/32 位深度,將按原深度讀取
4cv2.IMREAD_ANYCOLOR以任意顏色格式讀取(不強制轉換 BGR)
8cv2.IMREAD_IGNORE_ORIENTATION忽略圖像的 EXIF 方向元數據

示例

import cv2 as cv
# import numpy as np
if __name__ == '__main__':# 讀取圖像為灰度圖cat = cv.imread('../images/1.jpg',cv.IMREAD_GRAYSCALE)# 顯示圖像cv.imshow('cat', cat)cv.waitKey(0)cv.destroyAllWindows()

3.2 對已有圖片轉換

基本格式:

cv2.cvtColor(img, code)

參數說明:

  • img:輸入圖像,可以是一個Numpy數組繪著一個OpenCV的Mat對象
    • Mat 是一個核心的數據結構,主要用于存儲圖像和矩陣數據。在 Python 中使用 OpenCV 時,通常直接處理的是 NumPy 數組,cv2 模塊自動將 Mat 對象轉換為 NumPy 數組。二者之間的轉換是透明且自動完成的。例如,當你使用 cv2.imread() 函數讀取圖像時,返回的是一個 NumPy 數組,但在C++中則是 Mat 對象。
    • code:指定轉換的類型,可以使用預定義的轉換代碼。
      • 例如cv2.COLOR_RGB2GRAY表示從rgb到灰度圖像的轉換。

示例

import cv2 as cv
# import numpy as np
if __name__ == '__main__':# 讀取圖像cat = cv.imread('../images/1.jpg')# 顏色轉換 cv2.cvtColor(img, code)# 轉灰度gray_ = cv.cvtColor(cat, cv.COLOR_BGR2GRAY)# 轉HSVhsv = cv.cvtColor(cat, cv.COLOR_BGR2HSV)# 顯示圖片cv.imshow('cat', cat)cv.imshow('gray',gray_)cv.imshow('hsv',hsv)cv.waitKey(0)cv.destroyAllWindows()

4. 圖像灰度化

4.1 灰度圖概念

每個像素只有一個采樣顏色的圖像,這類圖像通常顯示為從最暗的黑色到最亮的白色灰度,盡管理論上這個采樣可以任何顏色的不同深淺,甚至可以是不同亮度上的不同顏色。灰度圖像與黑白圖像不同,在計算機圖像領域中黑白圖像只有黑色與白色兩種顏色;但是,灰度圖像在黑色與白色之間還有許多級的顏色深度。灰度圖像經常是在單個電磁波頻譜如可見光內測量每個像素的亮度得到的,用于顯示的灰度圖像通常用每個采樣像素8位的非線性尺度來保存,這樣可以有256級灰度。

原圖灰度圖

4.2 最大值灰度化

對于彩色圖像的每個像素,它會從R、G、B三個通道的值中選出最大的一個,并將其作為灰度圖像中對應位置的像素值。

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像img_0 = cv.imread('../images/pig.png')shape = img_0.shape # (h, w, c)# 創建一個新圖用于存放灰度像素img_1 = []# 最大值法(選取三通道中的最大值)for i in img_0:for j in i:img_1.append(max(j))img_2 = np.array(img_1).reshape(shape[0:2])cv.imshow('old',img_0)cv.imshow('gray', img_2)cv.waitKey(0)cv.destroyAllWindows()

4.3 平均值灰度化

對于彩色圖像的每個像素,它會將R、G、B三個通道的像素值全部加起來,然后再除以三,得到的平均值就是灰度圖像中對應位置的像素值。

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像img_0 = cv.imread('../images/1.jpg')shape = img_0.shape # (h, w, c)# 創建一個新圖用于存放灰度像素img_1 = []# 平均值法for i in img_0:for j in i:tmp = np.mean(j).astype(np.uint8)img_1.append(tmp)      img_2 = np.array(img_1).reshape(shape[0:2])cv.imshow('old',img_0)cv.imshow('gray', img_2)cv.waitKey(0)cv.destroyAllWindows()

4.4 加權均值灰度化

對于彩色圖像的每個像素,它會按照一定的權重去乘以每個通道的像素值,并將其相加,得到最后的值就是灰度圖像中對應位置的像素值。本實驗中,權重的比例為: R乘以0.299G乘以0.587B乘以0.114,這是經過大量實驗得到的一個權重比例,也是一個比較常用的權重比例

所使用的權重之和應該等于1。這是為了確保生成的灰度圖像素值保持在合理的亮度范圍內,并且不會因為權重的比例不當導致整體過亮或過暗。

opencv中的灰度化默認使用的加權均值

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像img_0 = cv.imread('../images/1.jpg')shape = img_0.shape # (h, w, c)# 創建一個新圖用于存放灰度像素img_1 = []# 權重weights = np.array([1/4,1/2,1/4])# 加權均值法for i in img_0:for j in i:tmp = np.average(j,weights=weights).astype(np.uint8)img_1.append(tmp)img_2 = np.array(img_1).reshape(shape[0:2])cv.imshow('old',img_0)cv.imshow('gray', img_2)cv.waitKey(0)cv.destroyAllWindows()

5. 圖像二值化處理

將某張圖像的所有像素改成只有兩種值之一。

5.1 二值圖像

一幅二值圖像的二維矩陣僅由0、1兩個值構成,“0”代表黑色,“1”代白色。由于每一像素(矩陣中每一元素)取值僅有0、1兩種可能,所以計算機中二值圖像的數據類型通常為1個二進制位。二值圖像通常用于文字、線條圖的掃描識別(OCR)和掩膜圖像的存儲。
二值化
其操作的圖像也必須是灰度圖。也就是說,二值化的過程,就是將一張灰度圖上的像素根據某種規則修改為0和maxval(maxval表示最大值,一般為255,顯示白色)兩種像素值,使圖像呈現黑白的效果,能夠幫助我們更好地分析圖像中的形狀、邊緣和輪廓等特征。

  • 特點和功能:

    • 簡便:降低計算量和計算需求,加快處理速度。
    • 節約資源:二值圖像占用空間遠小于彩色圖。
    • 邊緣檢測:二值化常作為邊緣檢測的預處理步驟,因為簡化后的圖易于識別出輪廓和邊界。

全局閾值法基本格式:

_,binary = cv2.threshold(img,thresh,maxval,type)

參數說明:

  • img:輸入圖像,要進行二值化處理的灰度圖。
  • thresh:設定的閾值。當像素值大于(或小于,取決于閾值類型)thresh時,該像素被賦予的值。
  • type:閾值處理的類型。
  • 返回值:
    • 第一個值(通常用下劃線表示):計算出的閾值,若使用自適應閾值法,會根據算法自動計算出這個值。
    • 第二個值(binary):二值化后的圖像矩陣。與輸入圖像尺寸相同。

5.2 閾值法(THRESH_BINARY)

閾值法就是通過設置一個閾值,將灰度圖中的每一個像素值與該閾值進行比較,小于等于閾值的像素就被設置為0(通常代表背景)大于閾值的像素就被設置為maxval(通常代表前景)。對于我們的8位圖像(0~255)來說,通常是設置為255。
二值化
示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# 二值化 閾值法thresh, binary = cv.threshold(gray_, 127, 255, cv.THRESH_BINARY)print(thresh)# 顯示效果cv.imshow('binary', binary)cv.waitKey(0)cv.destroyAllWindows()

5.3 反閾值法(THRESH_BINARY_INV)

顧名思義,就是與閾值法相反。反閾值法是當灰度圖的像素值大于閾值時,該像素值將會變成0(黑),當灰度圖的像素值小于等于閾值時,該像素值將會變成maxval。
反閾值法

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# 二值化 反閾值法thresh, binary_inv = cv.threshold(gray_, 127, 255, cv.THRESH_BINARY_INV)print(thresh)# 顯示效果cv.imshow('binary_inv', binary_inv)cv.waitKey(0)cv.destroyAllWindows()

5.4 截斷閾值法(THRESH_TRUNC)

截斷閾值法,指將灰度圖中的所有像素與閾值進行比較,像素值大于閾值的部分將會被修改為閾值,小于等于閾值的部分不變。
截斷閾值法

經過截斷閾值法處理過的二值化圖中的最大像素值就是閾值,此時參數maxval不起作用

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# 二值化 截斷閾值法_, trunc = cv.threshold(gray_,127,255, cv.THRESH_TRUNC)# 顯示效果cv.imshow('trunc', trunc)cv.waitKey(0)cv.destroyAllWindows()

5.5 低閾值零處理(THRESH_TOZERO)

低閾值零處理,字面意思,就是像素值小于等于閾值的部分被置為0(也就是黑色),大于閾值的部分不變。
低閾值零處理

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# 低閾值零處理_, tozero = cv.threshold(gray_,127,255, cv.THRESH_TOZERO)# 顯示效果cv.imshow('tozero', tozero)cv.waitKey(0)cv.destroyAllWindows()

5.6 超閾值零處理(THRESH_TOZERO_INV)

超閾值零處理就是將灰度圖中的每個像素與閾值進行比較,像素值大于閾值的部分置為0(也就是黑色),像素值小于等于閾值的部分不變。

超閾值零處理

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# 超閾值零處理_, tozero_inv = cv.threshold(gray_,127,255, cv.THRESH_TOZERO_INV)# 顯示效果cv.imshow('tozero_inv', tozero_inv)cv.waitKey(0)cv.destroyAllWindows()

5.7 OTSU閾值法

cv2.THRESH_OTS 并不是一個有效的閾值類型或標。THRESH_OTSU 本身并不是一個獨立的閾值化方法,而是與 OpenCV 中的二值化方法結合使用的一個標志。具體來說,THRESH_OTSU 通常與 THRESH_BINARYTHRESH_BINARY_INV 結合使用。在實際應用中,如果你使用 THRESH_OTSU 標志但沒有指定其他二值化類型,默認情況下它會與 THRESH_BINARY 結合使用。也就是說,當你僅指定了 cv2.THRESH_OTSU,實際上等同于同時指定了 cv2.THRESH_BINARY + cv2.THRESH_OTSU

在介紹OTSU閾值法之前,我們首先要了解一下雙峰圖片的概念。

雙峰圖片就是指灰度圖的直方圖上有兩個峰值,直方圖就是對灰度圖中每個像素值的點的個數的統計圖,如下圖所示。
雙峰圖

  • 灰度圖直方圖的基礎概念
  1. 灰度級
    • 在灰度圖像中,每個像素的值代表其亮度,通常范圍是 0 到 255(對于 8 位灰度圖像)。
    • 0 表示黑色,255 表示白色,中間的值表示不同程度的灰色。
  2. 直方圖定義
    • 直方圖是一個柱狀圖,其中 x 軸表示灰度級(從 0 到 255),y 軸表示對應灰度級在圖像中出現的次數(頻率)。
    • 每個柱子的高度代表該灰度級在圖像中出現的像素數量。

OTSU算法是通過一個值將這張圖分前景色和背景色(也就是灰度圖中小于這個值的是一類,大于這個值的是一類。例如,如果你設置閾值為128,則所有大于128的像素點可以被視作前景,而小于等于128的像素點則被視為背景。),通過統計學方法(最大類間方差)來驗證該值的合理性,當根據該值進行分割時,使用最大類間方差計算得到的值最大時,該值就是二值化算法中所需要的閾值。通常該值是從灰度圖中的最小值加1開始進行迭代計算,直到灰度圖中的最大像素值減1,然后把得到的最大類間方差值進行比較,來得到二值化的閾值。以下是一些符號規定:

T:閾值

N0N_{0}N0?:前景像素點數

N1N_{1}N1?:背景像素點數

ω0\omega_{0}ω0?:前景的像素點數占整幅圖像的比例

ω1\omega_{1}ω1?:背景的像素點數占整幅圖像的比例

U0\mathcal{U_{0}}U0?:前景的平均像素值

U1\mathcal{U_{1}}U1?:背景的平均像素值

U\mathcal{U}U:整幅圖的平均像素值

rows×cols:圖像的行數和列數

下面舉個例子,有一張大小為4×4的圖片,假設閾值T為1,則:
otsu

也就是這張圖片根據閾值1分為了前景(像素為2的部分)和背景(像素為0)的部分,并且計算出了OTSU算法所需要的各個數據,根據上面的數據,我們給出計算類間方差的公式:
g=ω0(μ0?μ)2+ω1(μ1?μ)2g=\omega_{0}(\mu_{0}-\mu)^{2}+\omega_{1}(\mu_{1}-\mu)^{2} g=ω0?(μ0??μ)2+ω1?(μ1??μ)2
g就是前景與背景兩類之間的方差,這個值越大,說明前景和背景的差別就越大,效果就越好。OTSU算法就是在灰度圖的像素值范圍內遍歷閾值T,使得g最大,基本上雙峰圖片的閾值T在兩峰之間的谷底。

通過OTSU算法得到閾值之后,就可以結合上面的方法根據該閾值進行二值化,在本實驗中有THRESH_OTSUTHRESH_INV_OTSU兩種方法,就是在計算出閾值后結合了閾值法和反閾值法。

THRESH_OTSUTHRESH_INV_OTSU
在這里插入圖片描述

注意:
使用OTSU算法計算閾值時,組件中的thresh參數將不再有任何作用。
THRESH_OTSU默認是cv2.THRESH_BINARY + cv2.THRESH_OTSU

示例
otsu反閾值法

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# OTSU結合反閾值_, otsu_inv = cv.threshold(gray_,127,255, cv.THRESH_OTSU + cv.THRESH_BINARY_INV)# 顯示效果cv.imshow('otsu_inv', otsu_inv)cv.waitKey(0)cv.destroyAllWindows()

5.8 自適應二值化

與二值化算法相比,自適應二值化更加適合用在明暗分布不均的圖片,因為圖片的明暗不均,導致圖片上的每一小部分都要使用不同的閾值進行二值化處理,這時候傳統的二值化算法就無法滿足我們的需求了,于是就出現了自適應二值化。

自適應二值化方法會對圖像中的所有像素點計算其各自的閾值,這樣能夠更好的保留圖片里的一些信息。自適應二值化組件內容如下圖所示:


基本格式:

cv2.adaptiveThreshold(image_np_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 10)

參數說明:

maxval:最大閾值,一般為255

adaptiveMethod:小區域閾值的計算方式:

ADAPTIVE_THRESH_MEAN_C:小區域內取均值

ADAPTIVE_THRESH_GAUSSIAN_C:小區域內加權求和,權重是個高斯核

thresholdType:二值化方法,只能使用THRESH_BINARYTHRESH_BINARY_INV,也就是閾值法和反閾值法

blockSize:選取的小區域的面積,如7就是7*7的小塊。

c:最終閾值等于小區域計算出的閾值再減去此值

5.8.1 取均值

假如我們使用的小區域是3*3的,那么就會從圖片的左上角開始(也就是像素值為162的地方)計算其鄰域內的平均值,如果處于邊緣地區就會對邊界進行填充,填充值就是邊界的像素點,如下圖所示:

那么對于左上角像素值為162的這個點,161(也就是上圖中括號內的計算結果,結果會進行取整)就是根據平均值計算出來的閾值,接著減去一個固定值C,得到的結果就是左上角這個點的二值化閾值了,接著根據選取的是閾值法還是反閾值法進行二值化操作。緊接著,向右滑動計算每個點的鄰域內的平均值,直到計算出右下角的點的閾值為止。我們所用到的不斷滑動的小區域被稱之為核,比如3*3的小區域叫做3*3的核,并且核的大小都是奇數個,也就是3*3、5*5、7*7等。(取奇數個是為了能有中心)

自適應二值化(Adaptive Thresholding)的核心思想就是為圖像中的每個像素點計算一個局部閾值。這種方法與全局閾值化不同,后者對整個圖像使用同一個固定的閾值。而在自適應二值化中,每個像素的閾值是基于其周圍鄰域內的像素值動態確定的。

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# 自適應二值化adaption_mean = cv.adaptiveThreshold(gray_, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY,3,2)# 顯示效果cv.imshow('adaption_mean', adaption_mean)cv.waitKey(0)cv.destroyAllWindows()
5.8.2 加權求和(高斯法)

對小區域內的像素進行加權求和得到新的閾值,其權重值來自于高斯分布。

高斯分布,通過概率密度函數來定義高斯分布,一維高斯概率分布函數為:
p(y)=1σ2πe?(y?μ)22σ2p(y)={\frac{1}{\sigma{\sqrt{2\pi}}}}e^{{\frac{-(y-\mu)^{2}}{2\sigma^{2}}}} p(y)=σ2π?1?e2σ2?(y?μ)2?
通過改變函數中和的值,我們可以得到如下圖像,其中均值為μ\muμ,標準差為σ2\sigma^{2}σ2
高斯分布

此時我們拓展到二維圖像,一般情況下我們使x軸和y軸的相等并且,此時我們可以得到二維高斯函數的表達式為:
g(x,y)=12πσ2e?(x2+y2)2σ2g(x,y)=\frac{1}{2\pi\sigma ^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma^{2}}} g(x,y)=2πσ21?e?2σ2(x2+y2)?
高斯概率函數是相對于二維坐標產生的,其中(x,y)為點坐標,要得到一個高斯濾波器模板,應先對高斯函數進行離散化,將得到的值作為模板的系數。例如:要產生一個3*3的高斯權重核,以核的中心位置為坐標原點進行取樣,其周圍的坐標如下圖所示(x軸水平向右,y軸豎直向上)

將坐標帶入上面的公式中,即可得到一個高斯權重核。

而在opencv里,當kernel(小區域)的尺寸為1、3、5、7并且用戶沒有設置sigma的時候(sigma <= 0),核值就會取固定的系數,這是一種默認的值是高斯函數的近似。

kernel尺寸核值
1[1]
3[0.25, 0.5, 0.25]
5[0.0625, 0.25, 0.375, 0.25, 0.0625]
7[0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125]

比如kernel的尺寸為3*3時,使用
[0.250.50.25]×[0.250.50.25]\left[\begin{array}{c}{{0.25}}\\ {{0.5}}\\ {{0.25}}\end{array}\right]\times\left[0.25~~~~0.5~~~~0.25\right] ?0.250.50.25??×[0.25????0.5????0.25]
進行矩陣的乘法,就會得到如下的權重值,其他的類似。
kernel=[0.06250.1250.06250.1250.250.1250.06250.1250.0625]kernel=\left[\begin{array}{c}{{0.0625~~~0.125~~~0.0625}}\\{{0.125~~~~0.25~~~~0.125}}\\ {{0.0625~~~0.125~~~0.0625}} \end{array}\right] kernel=?0.0625???0.125???0.06250.125????0.25????0.1250.0625???0.125???0.0625??
通過這個高斯核,即可對圖片中的每個像素去計算其閾值,并將該閾值減去固定值得到最終閾值,然后根據二值化規則進行二值化。

而當kernels尺寸超過7的時候,如果sigma設置合法(用戶設置了sigma),則按照高斯公式計算.當sigma不合法(用戶沒有設置sigma),則按照如下公式計算sigma的值:
σ=0.3?((ksize?1)?0.5?1)+0.8\sigma=0.3*\big((k s i z e-1)*0.5-1\big)+0.8 σ=0.3?((ksize?1)?0.5?1)+0.8
某像素點的閾值計算過程如下圖所示:

首先還是對邊界進行填充,然后計算原圖中的左上角(也就是162像素值的位置)的二值化閾值,其計算過程如上圖所示,再然后根據選擇的二值化方法對左上角的像素點進行二值化,之后核向右繼續計算第二個像素點的閾值,第三個像素點的閾值…直到右下角(也就是155像素值的位置)為止。

當核的大小不同時,僅僅是核的參數會發生變化,計算過程與此是一樣的。

示例

import cv2 as cv
import numpy as np
if __name__ == '__main__':# 讀取圖像flower = cv.imread('../images/flower.png')# 調整圖片大小flower = cv.resize(flower,(360, 360))# 灰度化處理gray_ = cv.cvtColor(flower, cv.COLOR_BGR2GRAY)# 自適應二值化--高斯核gauss = cv.adaptiveThreshold(gray_, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY,3,2)# 顯示效果cv.imshow('gauss', gauss)cv.waitKey(0)cv.destroyAllWindows()

二、圖像仿射變換

1. 圖像翻轉(圖像鏡像旋轉)

在OpenCV中,圖片的鏡像旋轉是以圖像的中心為原點進行鏡像翻轉的。
基本格式:

cv2.flip(img,flipcode

參數說明:

  • im.\ 要翻轉的圖像
  • flipcode: 指定翻轉類型的標志
    • flipcode=0: 垂直翻轉,圖片像素點沿x軸翻轉
    • flipcode>0: 水平翻轉,圖片像素點沿y軸翻轉
    • flipcode<0: 水平垂直翻轉,水平翻轉和垂直翻轉的結合

示例

import cv2 as cvif __name__ == '__main__':# 讀取圖片face = cv.imread('../images/face.png')# flipcode = 0 垂直翻轉,圖片像素點沿x軸翻轉flip_0 = cv.flip(face, 0)# flipcode >0 水平翻轉,圖片像素點沿y軸翻轉flip_1 = cv.flip(face, 2)# flipcode <0 水平垂直翻轉,水平翻轉和垂直翻轉的結合flip__1 = cv.flip(face, -1)# 顯示效果cv.imshow('face', face)cv.imshow('flip_0', flip_0)cv.imshow('flip_1', flip_1)cv.imshow('flip_-1', flip__1)cv.waitKey(0)cv.destroyAllWindows()

2.仿射變換

? 仿射變換(Affine Transformation)是一種線性變換,保持了點之間的相對距離不變。

  • 仿射變換的基本性質

    • 保持直線
    • 保持平行
    • 比例不變性
    • 不保持角度和長度
  • 常見的仿射變換類型

    • 旋轉:繞著某個點或軸旋轉一定角度。
    • 平移:僅改變物體的位置,不改變其形狀和大小。
    • 縮放:改變物體的大小。
    • 剪切:使物體發生傾斜變形。

2.1 仿射變換的基本原理 – 單點旋轉

首先我們以最簡單的一個點的旋轉為例子,且以最簡單的情況舉例,令旋轉中心為坐標系中心O(0,0)O(0,0)O(00),假設有一點P0(x0,y0)P_{0}(x_{0},y_{0})P0?(x0?,y0?)P0P_{0}P0?離旋轉中心OOO的距離為rrrOP0OP_{0}OP0?與坐標軸x軸的夾角為α\alphaαP0P_{0}P0?繞O順時針旋轉θ\thetaθ角后對應的點為P(x,y)P(x,y)P(x,y)

那么我們可以得到如下關系:
x0=r×cos?αx_{0}=r\times\cos\alpha x0?=r×cosα

y0=r×sin?αy_{0}=r\times\sin\alpha y0?=r×sinα

x=r×cos?(α?θ)=rcos?αcos?θ+rsin?αsin?θ=x0cos?θ+y0sin?θx=r\times\cos(\alpha-\theta)=r\cos\alpha\cos\theta+r\sin\alpha\sin\theta=x_{0}\cos\theta+y_{0}\sin\theta x=r×cos(α?θ)=rcosαcosθ+rsinαsinθ=x0?cosθ+y0?sinθ

y=r×sin?(α?θ)=rsin?αcos?θ?rcos?αsin?θ=?x0sin?θ+y0cos?θy=r\times\sin(\alpha-\theta)=r\sin\alpha\cos\theta-r\cos\alpha\sin\theta=-x_{0}\sin\theta+y_{0}\cos\theta y=r×sin(α?θ)=rsinαcosθ?rcosαsinθ=?x0?sinθ+y0?cosθ

用矩陣來表示就是
[xy]=[cos?θsin?θ?sin?θcos?θ]?[x0y0]\left[\begin{array}{l l}{{x}}\\{{y}}\end{array}\right]=\left[\begin{array}{l l}{{\cos\theta~~~~\sin\theta}}\\{{-\sin\theta~~~~\cos\theta}}\\ \end{array}\right]*\left[\begin{array}{c}{{x_{0}}}\\{{y_{0}}}\end{array}\right] [xy?]=[cosθ????sinθ?sinθ????cosθ?]?[x0?y0??]
然而,在OpenCV中,旋轉時是以圖像的左上角為旋轉中心,且以逆時針為正方向,因此上面的例子中其實是個負值,那么該矩陣可寫為:
[xy]=[cos?θ?sin?θsin?θcos?θ]?[x0y0]\left[\begin{array}{l l}{{x}}\\{{y}}\end{array}\right]=\left[\begin{array}{l l}{{\cos\theta~~~~-\sin\theta}}\\{{\sin\theta~~~~\cos\theta}}\\ \end{array}\right]*\left[\begin{array}{c}{{x_{0}}}\\{{y_{0}}}\end{array}\right] [xy?]=[cosθ?????sinθsinθ????cosθ?]?[x0?y0??]
其中,
[cos?θ?sin?θsin?θcos?θ]\left[\begin{array}{l l}{{\cos\theta~~~~-\sin\theta}}\\{{\sin\theta~~~~\cos\theta}}\\ \end{array}\right] [cosθ?????sinθsinθ????cosθ?]
也被稱作旋轉矩陣。然而我們所要的不僅僅是可以圍繞圖像左上角進行旋轉,而是可以圍繞任意點進行旋轉。那么我們可以將其轉化成繞原點的旋轉,其過程為:

  1. 首先將旋轉點移到原點
  2. 按照上面的旋轉矩陣進行旋轉得到新的坐標點
  3. 再將得到的旋轉點移回原來的位置

也就是說,在以任意點為旋轉中心時,除了要進行旋轉之外,還要進行平移操作。那么當點經過平移后得到P點時,如下圖所示:

那么我們就可以得到:
x=x0+txx=x_{0}+t_{x} x=x0?+tx?

y=y0+tyy=y_{0}+t_{y} y=y0?+ty?

寫成矩陣的形式為:
[xy1]=[10tx01ty001]?[x0y01]\left[\begin{array}{l l l}{{x}}\\{{y}}\\{1}\end{array}\right]=\left[\begin{array}{c}{{1~~~~0~~~~t_{x}}}\\{{0~~~~1~~~~t_{y}}}\\{{0~~~~0~~~~1}} \end{array}\right]*\left[\begin{array}{c}{{x_0}}\\{{y_0}}\\{1}\end{array}\right] ?xy1??=?1????0????tx?0????1????ty?0????0????1????x0?y0?1??
于是
[10tx01ty001]\left[\begin{array}{l l l}{{1~~~~0~~~~t_{x}}}\\{{0~~~~1~~~~t_{y}}}\\{{0~~~~0~~~~1}} \end{array}\right] ?1????0????tx?0????1????ty?0????0????1??
也被叫做平移矩陣,相反的,從P移到點時,其平移矩陣為:
[10?tx01?ty001]\left[\begin{array}{l l l}{1}&{0}&{-\,t_{x}}\\ {0}&{1}&{-\,t_{y}}\\ {0}&{0}&{1}\end{array}\right] ?100?010??tx??ty?1??
我們將原始的旋轉矩陣也擴展到3*3的形式:
[xy1]=[cos?θ?sin?θ0sin?θcos?θ0001]?[x0y01]\begin{array}{l l l}{{\left[\begin{array}{c}{{x}}\\{{y}}\\{1} \end{array}\right]=\left[\begin{array}{c c c}{{\cos\theta}}&{{-\sin\theta}}&{{0}}\\ {{\sin\theta}}&{{\cos\theta}}&{{0}}\\ {{0}}&{{0}}&{{1}}\end{array}\right]*\left[\begin{array}{c}{{x_{0}}}\\{{y_{0}}}\\{{1}}\end{array}\right]}}\end{array} ?xy1??=?cosθsinθ0??sinθcosθ0?001????x0?y0?1???
從平移和旋轉的矩陣可以看出,3x3矩陣的前2x2部分是和旋轉相關的,第三列與平移相關。有了上面的表達式之后,我們就可以得到二維空間中繞任意點旋轉的旋轉矩陣了,只需要將旋轉矩陣先左乘
[10tx01ty001]\left[\begin{array}{l l l}{{1~~~~0~~~~t_{x}}}\\{{0~~~~1~~~~t_{y}}}\\{{0~~~~0~~~~1}} \end{array}\right] ?1????0????tx?0????1????ty?0????0????1??
,再右乘
[10?tx01?ty001]\left[\begin{array}{l l l}{1}&{0}&{-\,t_{x}}\\ {0}&{1}&{-\,t_{y}}\\ {0}&{0}&{1}\end{array}\right] ?100?010??tx??ty?1??
即可得到最終的矩陣其結果為:( 知道就好!!!)
M=[cos?θ?sin?θ(1?cos?θ)tx+ty?sin?θsin?θcos?θ(1?cos?θ)ty+tx?sin?θ001]M=\left[\begin{array}{l l l}{{\cos\theta~~-\sin\theta~~(1-\cos\theta)t_{x}+t_{y}*\sin\theta}}\\{{\sin\theta~~~\cos\theta~~~~~(1-\cos\theta)t_{y}+t_{x}*\sin\theta}}\\{{0~~~~~~~~~~~~~0~~~~~~~~~~~~~1}} \end{array}\right] M=?cosθ???sinθ??(1?cosθ)tx?+ty??sinθsinθ???cosθ?????(1?cosθ)ty?+tx??sinθ0?????????????0?????????????1??
于是我們就可以根據這個矩陣計算出圖像中任意一點繞某點旋轉后的坐標了,這個矩陣學名叫做仿射變換矩陣,而仿射變換是一種二維坐標到二維坐標之間的線性變換,也就是只涉及一個平面內二維圖形的線性變換,圖像旋轉就是仿射變換的一種。

? 仿射變換(Affine Transformation)是一種線性變換,保持了點之間的相對距離不變。

2.2 仿射變換函數

cv2.warpAffine(img,M,dsize)

參數說明:

  • img:輸入圖像。

  • M:2x3的變換矩陣,類型為np.float32

  • dsize:輸出圖像的尺寸,形式為(width,height)

示例

  • 旋轉
import cv2 as cv
import numpy as np# 利用仿射變換矩陣
if __name__ == '__main__':# 讀取圖片old = cv.imread('../images/1.jpg')shape = old.shape# 獲取旋轉的仿射矩陣M = cv.getRotationMatrix2D((shape[0]//2, shape[1]//2),-45, 1)# 旋轉new_rotation = cv.warpAffine(old, M, (shape[1],shape[0]))# 顯示對象cv.imshow('new_1', new_rotation)cv.waitKey(0)cv.destroyAllWindows()
  • 平移
import cv2 as cv
import numpy as np# 利用仿射變換矩陣
if __name__ == '__main__':# 讀取圖片old = cv.imread('../images/1.jpg')shape = old.shape# 獲取旋轉的仿射矩陣tx = -100ty = -50M = np.float32([[1, 0, tx],[0, 1, ty]])# 平移new_pingyi = cv.warpAffine(old, M, (shape[1],shape[0]))# 顯示對象cv.imshow('new_2', new_pingyi)cv.waitKey(0)cv.destroyAllWindows()
  • 縮放
import cv2 as cv
import numpy as np# 利用仿射變換矩陣
if __name__ == '__main__':# 讀取圖片old = cv.imread('../images/1.jpg')shape = old.shape# 獲取旋轉的仿射矩陣Sx = 0.5 Sy = 1.2M = np.float32([[ 1.5, 0, 0],[ 0, 0.5, 0]])# 縮放new_pingyi = cv.warpAffine(old, M, (shape[1],shape[0]))# 顯示對象cv.imshow('new_2', new_pingyi)cv.waitKey(0)cv.destroyAllWindows()

總結

今天我們學習了圖像顏色處理及圖像仿射變換,其中顏色處理重點掌握二值化的OTSU閾值法和自適應二值化,仿射變換用到了旋轉角和矩陣,總的來說知識與線性代數結合很緊密,需要有一定的數學基礎。
讓我們下期再見!


— opencv系列相關文章 —

opencv–day01–opencv基礎知識及基礎操作

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

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

相關文章

第一層nginx訪問url如何透傳到第二層nginx

要讓第一層Nginx將客戶端請求的URL完整透傳到第二層Nginx&#xff0c;關鍵在于正確配置proxy_pass指令及路徑拼接規則。以下是具體配置方法和注意事項&#xff1a; 核心配置原則 proxy_pass指令末尾是否添加/會直接影響URL的透傳方式&#xff1a; 不帶/&#xff1a;會將locatio…

【2025最新畢業設計】外賣點餐小程序(外賣點餐管理系統)

外賣點餐小程序的設計與實現技術大綱&#xff08;Vue.js Element UI&#xff09;需求分析與功能設計用戶需求調研&#xff1a;分析目標用戶群體的核心需求&#xff08;如快速點餐、支付便捷、訂單跟蹤等&#xff09;核心功能模塊劃分&#xff1a;用戶端&#xff08;登錄/注冊、…

兩臺電腦連接交換機,使用其中一臺電腦的網絡上網(NAT轉發)

場景 windows 電腦和 linux電腦連在同一臺交換機上&#xff0c;linux電腦有通過無線網絡。要實現Windows電腦通過交換機共享Linux電腦的無線網絡上網&#xff0c;需將Linux設為網關并進行網絡共享&#xff0c;步驟如下&#xff1a; 一、Linux電腦設置&#xff08;網關配置&…

OpenCV Mat UMat GpuMat Matx HostMem InputArray等設計哲學

一、概覽&#xff1a; GpuMat對應于cuda&#xff1b;HostMem 可以看作是一種特殊的Mat&#xff0c;其存儲對應cuda在主機分配的鎖頁內存&#xff0c;可以不經顯示download upload自動轉變成GpuMat&#xff08;但是和GpuMat并無繼承關系&#xff09;&#xff1b;UMat對應于openc…

ATR2652SGNSS全頻段低噪聲放大器

ATR2652S是一款具有高增益、低噪聲系數的低噪聲放大器芯片。支持GNSS全頻段信號&#xff0c;同時GNSS 的兩個頻段可以應用于GNSS雙頻導航接收機中。 采用先進的 SiGe 工藝設計和制作&#xff0c;工藝穩定&#xff0c;低噪聲放大器在 GNSS 整個頻段內可以獲得非常好的射頻性能&a…

大數據中心——解讀60頁IDC云數據中心機房運維服務解決方案【附全文閱讀】

該方案主要面向云數據中心運營管理者、IT 運維人員、企業決策者等&#xff0c;旨在解決云資源和業務網絡管理難題&#xff0c;提升 IT 資源掌控能力。方案核心是 EVM VirtualViz 仿真可視化系統&#xff0c;它整合多源數據&#xff0c;提供 3D 仿真展示&#xff0c;實現數據中心…

環境變量-進程概念(7)

文章目錄Linux 真實調度算法1. queue[140]2. bitmap[5] 位圖3. nr_active4. 活躍進程與過期進程環境變量1. 基本概念2. 命令行參數3. PATH 環境變量4. 環境變量具體操作Linux 真實調度算法 下圖是Linux2.6內核中進程隊列的數據結構&#xff0c;也有Linux2.6內核進程O(1)調度算…

為什么數組可以做到時間復雜度為O(1)的隨機訪問

這個問題涉及數組底層結構與內存尋址機制 一、數組元素在內存中連續存儲 數組在內存中會開辟一塊連續地址空間。假設數組A為int類型&#xff0c;共有n個元素&#xff0c;每個元素大小為4字節&#xff0c;那么他們在內存中的存儲結構可能如下&#xff1a;內存地址數組元素A0x100…

《使用Qt Quick從零構建AI螺絲瑕疵檢測系統》——5. 集成OpenCV:讓程序擁有“視力”

目錄一、概述1.1 背景介紹&#xff1a;賦予應用“視力”1.2 學習目標二、集成OpenCV2.1 安裝OpenCV2.2 在Qt項目中配置CMake三、項目數據集介紹與準備四、圖像的橋梁&#xff1a;ImageProvider與格式轉換五、加載、轉換并顯示圖像六、總結與展望一、概述 1.1 背景介紹&#xf…

智慧駕駛疲勞檢測算法的實時性優化

智慧駕駛疲勞檢測&#xff1a;從技術突破到場景革命全球每年因疲勞駕駛引發的交通事故占比超20%&#xff0c;夜間及長途駕駛場景中這一比例更高。當駕駛員出現疲勞甚至暈倒等危險駕駛行為時&#xff0c;傳統檢測手段因依賴單一傳感器或受環境干擾&#xff0c;存在誤報率高、響應…

USRP X440

產品概述 USRP X440 是 Ettus Research 推出的高性能、多通道、寬帶軟件定義無線電&#xff08;SDR&#xff09;系統。基于 Xilinx Zynq UltraScale RFSoC 架構&#xff0c;它提供高密度、相干性的信號收發能力&#xff0c;幫助您快速構建雷達、電子戰&#xff08;EW&#xff0…

[特殊字符] GitHub 2025年7月月度精選項目 Top5

&#x1f680; GitHub 2025年7月月度精選項目 Top5 本月GitHub有哪些值得關注的優質開源項目&#xff1f;我從數千個新項目中&#xff0c;精選了5個有趣 實用 可演示的倉庫 無論你是開發者、AI愛好者、工具控&#xff0c;還是正在做副業產品&#xff0c;這篇文章都值得收藏&a…

微服務架構下的自動化測試策略調優經驗分享

微服務架構下,自動化測試策略需針對分布式特性、服務自治性和高耦合風險進行針對性調整的關鍵調整方向及實施方法: 一、??測試策略重構:分層與契約驅動?? 1. ??測試金字塔升級為鉆石模型?? ??調整邏輯??:傳統金字塔中UI測試占比過高,而微服務需強化契約測試與…

圖論:并查集

入門 久聞并查集的大名&#xff0c;今天來一探究竟&#xff0c;到底什么是并查集&#xff0c;并查集有什么用&#xff1f; 并查集(Disjoint Set Union, DSU)是一種處理不相交集合的合并及查詢問題的數據結構。 其實并查集的作用主要就有兩個&#xff1a; 1、將兩個元素添加到…

告別靜態文檔!Oracle交互式技術架構圖讓數據庫學習“活“起來

&#x1f5fa;? 當數據庫架構圖學會"互動" 想象一下&#xff0c;你正在學習Oracle數據庫架構&#xff0c;面對密密麻麻的靜態文檔和復雜的組件關系圖&#xff0c;是不是常常感到&#xff1a; 像在迷宮里找路&#xff0c;不知道組件間如何協作&#xff1f;想深入了…

day62-可觀測性建設-全鏈路監控zabbix+grafana

&#x1f31f;監控api接口 &#x1f50d;監控zabbix-api接口 生成API tokens命令行測試 curl -s -X POST -H "Content-Type: application/json-rpc" -d {"jsonrpc": "2.0","method": "host.get","params": {&quo…

通過Deepseek找工作

推送的結果如下,對應的AI提示詞在底部: 計算機方向遠程工作職位匯總 整合全球遠程技術崗位 | 支持全地域遠程辦公 | 涵蓋開發、安全、云計算等方向 覆蓋方向:8+個技術領域 薪資范圍:10K-40K/月 工作模式:100%遠程 遠程技術職位列表 職位名稱 技能要求 經驗要求 薪資…

vscode文件顏色,只顯示自己更改的文件顏色、剛git下來的庫,vscode打開后,顯示所有文件都被修改了

問題&#xff1a;git新的庫&#xff0c;然后我用vscode打開&#xff0c;默認顯示所有的文件都更改了&#xff0c;但是我打開他們修改的對比&#xff0c;沒有顯示任何有被修改的地方&#xff0c;是怎么回事 linux/wsl下這么設置就可以了&#xff1a;git config core.autocrlf in…

基于ENMeval包的MaxEnt模型參數優化總結

MaxEnt模型參數優化1. MaxEnt模型優化&#xff1a;增加RM&#xff0c;降低模型過擬合風險&#xff0c;簡易模型&#xff0c;平滑響應曲線&#xff0c;增強模型可解釋性和轉移性&#xff08;生物入侵&#xff09;2. 默認參數&#xff1a;FCLQHP&#xff0c;RM12.1. 基于優化的 M…

Docker實踐:使用Docker部署blog輕量級博客系統

Docker實踐&#xff1a;使用Docker部署blog輕量級博客系統一、blog系統介紹1.1 blog介紹1.2 個人博客系統介紹1.3 個人博客使用場景二、本地環境介紹2.1 本地環境規劃2.2 本次實踐介紹三、本地環境檢查3.1 檢查Docker服務狀態3.2 檢查Docker版本3.3 檢查docker compose 版本四、…