使用Python進(jìn)行圖像幾何變換的操作流程
算數(shù)操作
圖像的加法
OpenCV加法是飽和操作,Numpy加法是模運(yùn)算。
import cv2 import numpy as np x = np.uint8([250]) y = np.uint8([10]) print(x) # [[250]] print(y) # [[10]] print(cv2.add(x, y)) # [[255]] print(x + y) # [4]
OpenCV加法
# cv2.add() 是 OpenCV 中用于執(zhí)行圖像加法運(yùn)算的核心函數(shù),與 Python 的普通加法運(yùn)算符 (+) 不同,它使用飽和運(yùn)算防止溢出。 dst = cv2.add(src1, src2[, dst[, mask[, dtype]]])
| 參數(shù) | 類型 | 描述 |
|---|---|---|
src1 | numpy.ndarray | 第一個(gè)輸入數(shù)組(圖像) |
src2 | numpy.ndarray 或 標(biāo)量 | 第二個(gè)輸入數(shù)組或標(biāo)量值 |
dst | numpy.ndarray (可選) | 輸出數(shù)組(與輸入相同大小和類型) |
mask | numpy.ndarray (可選) | 8位單通道掩碼,指定要修改的輸出數(shù)組元素 |
dtype | int (可選) | 輸出數(shù)組的深度(如 cv2.CV_8U, cv2.CV_32F) |
中文標(biāo)題會(huì)亂碼,干脆使用英文標(biāo)題了,鍵盤按下任意鍵退出,只是關(guān)閉窗口程序不會(huì)結(jié)束。
import cv2
# 讀取兩張相同尺寸的圖像
img1 = cv2.imread("image1.jpg") # 替換為你的圖片路徑
img2 = cv2.imread("image2.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img1 is None or img2 is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
# 調(diào)整img2尺寸匹配img1
if img1.shape != img2.shape:
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) # 注意寬高順序
# 直接相加
result = cv2.add(img1, img2)
# 顯示結(jié)果
cv2.imshow("OpenCV Addition", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Numpy加法
很明顯直接相加的話圖像直接失真了。
result = img1 + img2
import cv2
# 讀取兩張相同尺寸的圖像
img1 = cv2.imread("image1.jpg") # 替換為你的圖片路徑
img2 = cv2.imread("image2.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img1 is None or img2 is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
# 調(diào)整img2尺寸匹配img1
if img1.shape != img2.shape:
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) # 注意寬高順序
# 直接相加
result = img1 + img2
# 顯示結(jié)果
cv2.imshow("Numpy Addition", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
圖像的混合
# cv2.addWeighted() 是 OpenCV 中最重要和最常用的圖像處理函數(shù)之一,用于實(shí)現(xiàn)圖像的加權(quán)混合(也稱為alpha混合)。 # dst = src1 × alpha + src2 × beta + gamma dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
| 參數(shù) | 類型 | 描述 | 默認(rèn)值 | 重要說明 |
|---|---|---|---|---|
src1 | numpy.ndarray | 第一個(gè)輸入圖像(矩陣) | 必填 | 支持多通道圖像(如BGR彩色 圖) |
alpha | float | 第一個(gè)圖像的權(quán)重系數(shù) | 必填 | 通常范圍0.0-1.0,但可為任意實(shí)數(shù) |
src2 | numpy.ndarray | 第二個(gè)輸入圖像(矩陣) | 必填 | 必須與src1尺寸和通道數(shù)相同 |
beta | float | 第二個(gè)圖像的權(quán)重系數(shù) | 必填 | 通常alpha + beta = 1.0 |
gamma | float | 添加到加權(quán)和的標(biāo)量值 | 必填 | 用于亮度調(diào)整,通常為0 |
dst | numpy.ndarray | 輸出圖像 | None | 可選,用于預(yù)分配輸出數(shù)組 |
dtype | int | 輸出數(shù)組的深度 | -1 | 可選,如cv2.CV_8U, cv2.CV_32F |
import cv2
# 讀取兩張相同尺寸的圖像
img1 = cv2.imread("image1.jpg") # 替換為你的圖片路徑
img2 = cv2.imread("image2.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img1 is None or img2 is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
# 調(diào)整img2尺寸匹配img1
if img1.shape != img2.shape:
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) # 注意寬高順序
# 圖像混合
result = cv2.addWeighted(img1, 0.3, img2, 0.7, 0)
# 顯示結(jié)果
cv2.imshow("Image Mixing", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
幾何變換
圖像縮放
對(duì)圖像進(jìn)行放大或縮小。
resized = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
參數(shù)詳解:
src: 輸入圖像 (numpy.ndarray)dsize: 輸出圖像尺寸 (tuple:(width, height))fx: 水平縮放因子 (float)fy: 垂直縮放因子 (float)interpolation: 插值方法 (默認(rèn)為cv2.INTER_LINEAR)
重要規(guī)則:必須指定 dsize 或 (fx, fy),但不能同時(shí)指定兩者
插值方法對(duì)比
| 插值方法 | 枚舉值 | 時(shí)間復(fù)雜度 | 質(zhì)量 | 適用場景 |
|---|---|---|---|---|
| 最近鄰插值 | cv2.INTER_NEAREST | O(1) | 低 | 像素藝術(shù)、實(shí)時(shí)處理 |
| 雙線性插值 | cv2.INTER_LINEAR | O(4) | 中 | 默認(rèn)選擇,平衡速度質(zhì)量 |
| 雙三次插值 | cv2.INTER_CUBIC | O(16) | 高 | 高質(zhì)量放大,照片處理 |
| 區(qū)域插值 | cv2.INTER_AREA | O(1) | 中高 | 縮小圖像首選 |
| Lanczos插值 | cv2.INTER_LANCZOS4 | O(64) | 極高 | 專業(yè)級(jí)放大,醫(yī)學(xué)影像 |
絕對(duì)尺寸
resized = cv2.resize(img, (400, 300))
相對(duì)尺寸
# 縮小為原圖的50% half_size = cv2.resize(img, None, fx=0.5, fy=0.5)
圖像平移
指定平移矩陣后,調(diào)用cv.warpAffine()平移圖像。
dst = cv2.warpAffine(
src,
M,
dsize,
dst=None,
flags=cv2.INTER_LINEAR,
borderMode=cv2.BORDER_CONSTANT,
borderValue=0
)必需參數(shù)
| 參數(shù) | 類型 | 描述 |
|---|---|---|
src | numpy.ndarray | 輸入圖像 (單通道或多通道) |
M | numpy.ndarray (2×3) | 2×3仿射變換矩陣 |
dsize | tuple | 輸出圖像尺寸 (width, height) |
可選參數(shù)
| 參數(shù) | 類型 | 默認(rèn)值 | 描述 |
|---|---|---|---|
dst | numpy.ndarray | None | 輸出圖像數(shù)組 (預(yù)分配內(nèi)存) |
flags | int | cv2.INTER_LINEAR | 插值方法 |
borderMode | int | cv2.BORDER_CONSTANT | 邊界填充模式 |
borderValue | scalar | 0 | 邊界填充值 (BORDER_CONSTANT時(shí)使用) |
M仿射變換矩陣
M = [ a11 a12 b1 ]
[ a21 a22 b2 ]變換類型與矩陣關(guān)系
| 變換類型 | 矩陣公式 | 說明 |
|---|---|---|
| 平移 | [[1, 0, tx], [0, 1, ty]] | tx, ty 為平移量 |
| 旋轉(zhuǎn) | cv2.getRotationMatrix2D(center, angle, scale) | 中心點(diǎn)、角度、縮放 |
| 縮放 | [[sx, 0, 0], [0, sy, 0]] | sx, sy 為縮放因子 |
| 傾斜 | [[1, shx, 0], [shy, 1, 0]] | shx, shy 為傾斜因子 |
| 組合變換 | M = M1 × M2 | 矩陣乘法組合多個(gè)變換 |
import cv2
import numpy as np
# 讀取兩張相同尺寸的圖像
img = cv2.imread("image1.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
# x移動(dòng)200px,y移動(dòng)150px
M = np.float32([[1, 0, 200], [0, 1, 150]]) # 平移矩陣
result = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
# 顯示結(jié)果
cv2.imshow("Image Translation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
圖像旋轉(zhuǎn)
調(diào)用cv.getRotationMatrix2D獲取旋轉(zhuǎn)矩陣,然后調(diào)用cv.warpAffine()進(jìn)行旋轉(zhuǎn)。
# 生成旋轉(zhuǎn)矩陣 retval = cv2.getRotationMatrix2D(center, angle, scale)
| 參數(shù) | 類型 | 描述 |
|---|---|---|
center | tuple (x, y) | 旋轉(zhuǎn)中心點(diǎn)坐標(biāo) |
angle | float | 旋轉(zhuǎn)角度(度),逆時(shí)針為正 |
scale | float | 縮放比例 (1.0 = 保持原大小) |
返回值:retval: 2×3 仿射變換矩陣 (numpy.ndarray, dtype=float64)
此時(shí)M:[[ 0.70710678 0.70710678 -50.33008589]
[ -0.70710678 0.70710678 418.49242405]]
import cv2
# 讀取兩張相同尺寸的圖像
img = cv2.imread("image1.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
# 旋轉(zhuǎn)中心,旋轉(zhuǎn)角度,縮放因子
M = cv2.getRotationMatrix2D((img.shape[1] / 2, img.shape[0] / 2), 45, 1) # 旋轉(zhuǎn)矩陣
# 進(jìn)行旋轉(zhuǎn)
result = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
# 顯示結(jié)果
cv2.imshow("Image Rotation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
仿射變換
調(diào)用getAffineTransform將創(chuàng)建變換矩陣,最后該矩陣傳遞給cv.warpAffine()進(jìn)行變換。
- 如果兩條線在變換前平行,變換后仍然平行。
- 位于同一直線上的點(diǎn)在變換后仍然位于同一直線上。
- 直線上點(diǎn)的比例關(guān)系在變換后保持不變。如果點(diǎn)C位于A和B之間,且AC:CB = m:n,則變換后這個(gè)比例關(guān)系仍然成立。
# 通過三對(duì)對(duì)應(yīng)點(diǎn)建立源圖像與目標(biāo)圖像之間的幾何映射關(guān)系 M = cv2.getAffineTransform(src, dst)
| 參數(shù) | 類型 | 描述 |
|---|---|---|
src | numpy.ndarray (3×2) | 源圖像中的三個(gè)點(diǎn)坐標(biāo) (float32) |
dst | numpy.ndarray (3×2) | 目標(biāo)圖像中的三個(gè)對(duì)應(yīng)點(diǎn)坐標(biāo) (float32) |
返回值:M: 2×3 仿射變換矩陣 (numpy.ndarray, dtype=float64)
此時(shí)M:[[ 1.26666667 0.6 -83.33333333]
[ -0.33333333 1. 66.66666667]]
import cv2
import numpy as np
# 讀取兩張相同尺寸的圖像
img = cv2.imread("image1.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
# 定義源圖像和目標(biāo)圖像的頂點(diǎn)
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
# 計(jì)算仿射變換矩陣
M = cv2.getAffineTransform(pts1, pts2)
# 進(jìn)行仿射變換
result = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
# 顯示結(jié)果
cv2.imshow("Affine Transformation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
透射變換
通過函數(shù)getPerspectiveTransform()找到變換矩陣,將cv.warpPerspective()進(jìn)行投射變換。
M = cv2.getPerspectiveTransform(src, dst[, solveMethod])
| 參數(shù) | 類型 | 描述 |
|---|---|---|
src | numpy.ndarray (4×2) | 源圖像中的四個(gè)點(diǎn)坐標(biāo) (float32) |
dst | numpy.ndarray (4×2) | 目標(biāo)圖像中的四個(gè)對(duì)應(yīng)點(diǎn)坐標(biāo) (float32) |
solveMethod | int | 矩陣求解方法 (默認(rèn) DECOMP_LU) |
此時(shí)T:[[ 1.05587376e+00 9.18151097e-02 -6.50969128e+01]
[ 4.69010049e-02 1.12562412e+00 -7.57920240e+01]
[ 1.83251448e-04 5.13337001e-04 1.00000000e+00]]
dst = cv2.warpPerspective(
src,
M,
dsize,
dst=None,
flags=cv2.INTER_LINEAR,
borderMode=cv2.BORDER_CONSTANT,
borderValue=0
)| 參數(shù) | 類型 | 描述 | 默認(rèn)值 |
|---|---|---|---|
src | numpy.ndarray | 輸入圖像 (單通道或多通道) | - |
M | numpy.ndarray (3×3) | 透 視變換矩陣 (單應(yīng)性矩陣) | - |
dsize | tuple | 輸出圖像尺寸 (width, height) | - |
dst | numpy.ndarray | 輸出圖像 (預(yù)分配內(nèi)存) | None |
flags | int | 插值方法 + 可選標(biāo)志 | INTER_LINEAR |
borderMode | int | 邊界處理模式 | BORDER_CONSTANT |
borderValue | scalar | 邊界填充值 | 0 |
import cv2
import numpy as np
# 讀取兩張相同尺寸的圖像
img = cv2.imread("image1.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
# 透 視變換
# 定義源點(diǎn)
pts1=np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
# 定義目標(biāo)點(diǎn)
pts2=np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
# 獲取透 視變換矩陣
T=cv2.getPerspectiveTransform(pts1, pts2)
result = cv2.warpPerspective(img, T, (img.shape[1], img.shape[0]))
# 顯示結(jié)果
cv2.imshow("Transmission Transformation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
圖像金字塔
向上采樣:cv.pyrUp()
向下采樣:cv.pyrDown()
dst = cv2.pyrUp(
src,
dst=None,
dstsize=None,
borderType=cv2.BORDER_DEFAULT
)
dst = cv2.pyrDown(
src,
dst=None,
dstsize=None,
borderType=cv2.BORDER_DEFAULT
)| 參數(shù) | 類型 | 描述 | 默認(rèn)值 |
|---|---|---|---|
src | numpy.ndarray | 輸入圖像 | - |
dst | numpy.ndarray | 輸出圖像 (可選) | None |
dstsize | tuple | 輸出圖像大小 (width, height) | None |
borderType | int | 邊界填充類型 | cv2.BORDER_DEFAULT |
import cv2
import numpy as np
# 讀取兩張相同尺寸的圖像
img = cv2.imread("image1.jpg") # 替換為你的圖片路徑
# 檢查圖像是否成功讀取
if img is None:
print("錯(cuò)誤:無法讀取圖像文件")
exit()
up_img = cv2.pyrUp(img) # 上采樣
down_img = cv2.pyrDown(img) # 下采樣
# 顯示結(jié)果
cv2.imshow("enlarge", up_img)
cv2.imshow("Image Pyramid", img)
cv2.imshow("shrink", down_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
| 特性 | 圖像金字塔 | 圖像縮放 |
|---|---|---|
| 目的 | 創(chuàng)建多尺度表示用于特征分析 | 改變圖像尺寸以適應(yīng)特定需求 |
| 輸出 | 一組不同尺度的圖像序列 | 單一尺寸的圖像 |
| 數(shù)學(xué)基礎(chǔ) | 高斯平滑+下采樣/上采樣 | 插值算法 |
| 可逆性 | 不可逆(信息損失) | 部分可逆(取決于算法) |
| 典型應(yīng)用 | 多尺度特征檢測、圖像融合 | 顯示適配、預(yù)處理、存儲(chǔ)優(yōu)化 |
| OpenCV函數(shù) | pyrUp(), pyrDown() | resize() |
以上就是使用Python進(jìn)行圖像幾何變換的操作流程的詳細(xì)內(nèi)容,更多關(guān)于Python圖像幾何變換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python借助ChatGPT讀取.env實(shí)現(xiàn)文件配置隔離保障私有數(shù)據(jù)安全
這篇文章主要為大家介紹了python讀取.env實(shí)現(xiàn)文件配置隔離保障私有數(shù)據(jù)安全,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
使用 Python 列出串口的實(shí)現(xiàn)方法
有時(shí)在編程時(shí),我們需要獲取有關(guān)系統(tǒng)中可用通信端口的信息, 我們將討論如何使用 Python 來做到這一點(diǎn),將討論使用串口或 com 端口的通信, 我們將深入探索 Python 包,以幫助我們獲得系統(tǒng)的可用通信端口,感興趣的朋友一起看看吧2023-08-08
OpenCV目標(biāo)檢測Meanshif和Camshift算法解析
這篇文章主要為大家介紹了OpenCV目標(biāo)檢測Meanshif和Camshift算法解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
Python中強(qiáng)大的函數(shù)map?filter?reduce使用詳解
Python是一門功能豐富的編程語言,提供了許多內(nèi)置函數(shù),以簡化各種編程任務(wù),在Python中,map(),filter()和reduce()是一組非常有用的函數(shù),它們?cè)试S對(duì)可迭代對(duì)象進(jìn)行操作,從而實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換、篩選和累積等操作,本文將詳細(xì)介紹這三個(gè)函數(shù),包括它們的基本用法和示例代碼2023-11-11
python中的queue隊(duì)列類型及函數(shù)用法
這篇文章主要介紹了python中的queue隊(duì)列類型及函數(shù)用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
python安裝TA-Lib庫報(bào)錯(cuò)問題的解決方法
TaLib是一個(gè)Python金融指數(shù)處理庫,包含了很多技術(shù)分析里的常用參數(shù)指標(biāo),例如MA、SMA、WMA、MACD、ATR等,這篇文章主要給大家介紹了關(guān)于python安裝TA-Lib庫報(bào)錯(cuò)問題的解決方法,需要的朋友可以參考下2024-01-01

