計算機視覺(opencv)實戰十八——圖像透視轉換


圖像透視變換詳解與實戰

在圖像處理中,透視變換(Perspective Transform) 是一種常見的幾何變換,用來將圖像中某個四邊形區域拉伸或壓縮,映射到一個矩形區域。常見應用場景包括:

  • 糾正拍照時的傾斜(如手機拍發票、拍文檔)

  • 從復雜背景中提取規則區域(如車牌識別)

  • 圖像投影變換、鳥瞰視圖生成

本文將通過一個完整案例,帶你從圖像讀取、輪廓檢測,到透視變換、結果后處理,逐步完成發票/文件的自動矯正。

圖片準備:


1. 導入依賴與輔助函數

import numpy as np
import cv2

我們首先導入 NumPyOpenCV,這是圖像處理的核心庫。

圖像顯示函數

def cv_show(name, img):"""顯示圖像"""cv2.imshow(name, img)cv2.waitKey(0)
  • cv2.imshow 用于顯示圖像窗口

  • cv2.waitKey(0) 表示等待鍵盤輸入后才關閉窗口,便于逐步觀察每一步結果


2. 坐標排序函數:order_points

def order_points(pts):rect = np.zeros((4, 2), dtype="float32")s = pts.sum(axis=1)rect[0] = pts[np.argmin(s)]  # 左上角點 (x+y最小)rect[2] = pts[np.argmax(s)]  # 右下角點 (x+y最大)diff = np.diff(pts, axis=1)rect[1] = pts[np.argmin(diff)]  # 右上角 (y-x最小)rect[3] = pts[np.argmax(diff)]  # 左下角 (y-x最大)return rect

在透視變換中,必須保證四個點的順序一致(左上、右上、右下、左下),否則會導致映射結果錯誤。
該函數通過:

  • x+y 最小 → 左上角

  • x+y 最大 → 右下角

  • y-x 最小 → 右上角

  • y-x 最大 → 左下角
    來對四點坐標排序,保證后續計算穩定。


3. 核心函數:透視變換

def four_point_transform(image,pts):rect = order_points(pts)(tl, tr, br, bl) = rectwidthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))maxWidth = max(int(widthA), int(widthB))heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))maxHeight = max(int(heightA), int(heightB))dst = np.array([[0, 0], [maxWidth - 1, 0],[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype="float32")M = cv2.getPerspectiveTransform(rect, dst)warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))return warped

步驟解析:

  1. 排序四點:保證輸入順序一致

  2. 計算目標矩形寬高:根據兩條對邊長度取最大值,保證變換后不丟失內容

  3. 構建目標點集:從 (0,0) 開始構建新的矩形頂點

  4. 求取透視變換矩陣cv2.getPerspectiveTransform()

  5. 執行透視變換cv2.warpPerspective() 輸出矯正后的圖像


?resize?函數等比例縮放(保持寬高比)

只需指定?width?或?height?中的一個,自動計算另一個

def resize(image, width=None, height=None, inter=cv2.INTER_AREA):dim = None(h, w) = image.shape[:2]if width is None and height is None:return imageif width is None:r = height / float(h)dim = (int(w * r), height)else:r = width / float(w)dim = (width, int(h * r))resized = cv2.resize(image, dim, interpolation=inter)return resized

4. 圖像預處理與輪廓檢測

image = cv2.imread('order.jpg')
cv_show('image',image)# 縮小圖像,便于處理
ratio = image.shape[0]/500
orig = image.copy()
image = resize(orig,height=500)
cv_show('1',image)print('STEP 1: 輪廓檢測')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 轉灰度
# 自動閾值二值化,突出目標區域
edged = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 尋找所有輪廓
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
# 繪制所有輪廓,便于可視化
image_contours = cv2.drawContours(image.copy(), cnts, -1, (0, 0, 255), 1)
cv_show('image_contours', image_contours)

這里先將圖像灰度化、二值化,再使用 cv2.findContours 獲取所有輪廓。然后在圖像上繪制輪廓,便于確認檢測效果。


5. 找到最大輪廓(目標區域)

# 找到最大輪廓并逼近為四邊形
print("STEP 2: 獲取最大輪廓")
screenCnt = sorted(cnts, key=cv2.contourArea, reverse=True)[0]  # 按面積排序,取最大
peri = cv2.arcLength(screenCnt, True)  # 計算周長
screenCnt = cv2.approxPolyDP(screenCnt, 0.05 * peri, True)  # 多邊形逼近,保留主要拐點
image_contour = cv2.drawContours(image.copy(), [screenCnt], -1, (0, 0, 255), 2)
cv_show('image_contour', image_contour)
  • sorted(..., key=cv2.contourArea, reverse=True) 按面積排序,取最大輪廓(一般就是發票/文件區域)

  • cv2.approxPolyDP 多邊形逼近,得到近似四邊形輪廓


6. 透視矯正 & 后處理

warped = four_point_transform(orig,screenCnt.reshape(4,2)*ratio)
cv2.imwrite('invoice_new.jpg',warped)
cv_show('xx',warped)# 轉灰度并二值化
gray1=cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY)
warped1=cv2.threshold(gray1,120,255,cv2.THRESH_BINARY)[1]
warped1=resize(warped1,height=500)
cv_show('warped1',warped1)# 腐蝕操作,去除噪點
kernel=np.ones((2,2),np.uint8)
erosion = cv2.erode(warped1,kernel,iterations=1)
cv_show('erosion',erosion)# 旋轉圖像
rotated_image1 =np.rot90(erosion, k=1)
cv_show('rotated_image1',rotated_image1)

后處理步驟:

  • 二值化:提高文字對比度,便于后續OCR識別

  • 腐蝕:去除孤立噪點,讓邊緣更干凈

  • 旋轉:如果方向不正,可手動或自動旋轉至正方向


7. 效果展示與應用

通過上述步驟,我們將一張傾斜、帶背景的發票圖像,處理成一個平整、純背景的圖像,便于后續的文字識別(OCR)。

這種方法廣泛應用于:

  • 發票/合同掃描矯正

  • 車牌識別

  • 桌面投影儀矯正

  • 透視校正后的AR場景識別


總結

本文完整實現了:

  1. 圖像預處理:縮放、灰度化、二值化

  2. 輪廓檢測:提取最大矩形區域

  3. 四點排序:確保透視變換穩定

  4. 透視矯正:將任意四邊形映射到規則矩形

  5. 后處理:二值化、腐蝕、旋轉

透視變換是圖像幾何處理中的關鍵技術,掌握它能夠讓你解決很多實際問題,尤其是文檔掃描、圖像矯正類任務。

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

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

相關文章

【飛書多維表格插件】

coze中添加飛書多維表格記錄插件 添加單條記錄 [{"fields":{"任務詳情":"選項1","是否完成":"未完成"}}]添加多條記錄 [{"fields":{"任務詳情":"選項1","是否完成":"已完…

Java基礎 9.14

1.Collection接口遍歷對象方式2-for循環增強增強for循環,可以代替iterator選代器,特點:增強for就是簡化版的iterator本質一樣 只能用于遍歷集合或數組package com.logic.collection_;import java.util.ArrayList; import java.util.Collectio…

數據結構(C語言篇):(十三)堆的應用

目錄 前言 一、堆排序 1.1 版本一:基于已有數組建堆、取棧頂元素完成排序 1.1.1 實現邏輯 1.1.2 底層原理 1.1.3 應用示例 1.1.4 執行流程 1.2 版本二:原地排序 —— 標準堆排序 1.2.1 實現邏輯 1.2.2 底層原理 1.2.3 時間復雜度計算…

4步OpenCV-----掃秒身份證號

這段代碼用 OpenCV 做了一份“數字模板字典”,然后在銀行卡/身份證照片里自動找到身份證號那一行,把每個數字切出來跟模板比對,最終輸出并高亮顯示出完整的身份證號碼,下面是代碼解釋:模塊 1 工具箱(通用函…

馮諾依曼體系:現代計算機的基石與未來展望

馮諾依曼體系:現代計算機的基石與未來展望 引人入勝的開篇 當你用手機刷視頻、用電腦辦公時,是否想過這些設備背后共享的底層邏輯?從指尖輕滑切換APP,到電腦秒開文檔,這種「無縫銜接」的體驗,其實藏著一個改…

前端基礎 —— C / JavaScript基礎語法

以下是對《3.JavaScript(基礎語法).pdf》的內容大綱總結:---📘 一、JavaScript 簡介 - 定義:腳本語言,最初用于表單驗證,現為通用編程語言。 - 應用:網頁開發、游戲、服務器(Node.js&#xff09…

springboot 二手物品交易系統設計與實現

springboot 二手物品交易系統設計與實現 目錄 【SpringBoot二手交易系統全解析】從0到1搭建你的專屬平臺! 🔍 需求確認:溝通對接 🗣 📊 系統功能結構:附思維導圖 ☆開發技術: &#x1f6e…

【Android】可折疊式標題欄

在 Android 應用開發中,精美的用戶界面可以顯著提升應用品質和用戶體驗。Material Design 組件中的 CollapsingToolbarLayout 能夠為應用添加動態、流暢的折疊效果,讓標題欄不再是靜態的元素。本文將深入探討如何使用 CollapsingToolbarLayout 創建令人驚…

Debian13下使用 Vim + Vimspector + ST-LINK v2.1 調試 STM32F103 指南

1. 硬件準備與連接 1.1 所需硬件 STM32F103C8T6 最小系統板ST-LINK v2.1 調試器連接線(杜邦線) 1.2 硬件連接 ST-LINK v2.1 ? STM32F103C8T6 連接方式:ST-LINK v2.1 引腳STM32F103C8T6 引腳功能說明SWDIOPA13數據線SWCLKPA14時鐘線GNDGND共地…

第21課:成本優化與資源管理

第21課:成本優化與資源管理 課程目標 掌握計算資源優化 學習成本控制策略 了解資源調度算法 實踐實現成本優化系統 課程內容 21.1 成本分析框架 成本分析系統 class CostAnalysisFramework {constructor(config) {this.config

SAP HANA Scale-out 04:CalculationView優化

CV執行過程計算視圖激活時,生成Stored ModelSELECT查詢時:首先將Stored Model實例化為runtime Model 計算引擎執行優化,將runtime Model轉換為Optimized Runtime ModelOptimized Runtime Model通過SQL Optimizer進行優化計算引擎優化特性說明…

鴻蒙審核問題——Scroll中嵌套了List/Grid時滑動問題

文章目錄背景原因解決辦法1、借鑒Flutter中的解決方式,如下圖2、鴻蒙Next中對應的解決方式,如下圖3、官方文檔回訪背景 來源一次審核被拒的情況。也是出于粗心導致的。之前在flutter項目中也是遇到過這種問題的。其實就是滾動視圖內嵌滾動視圖造成的&am…

測試電商購物車功能,設計測試case

在電商場景中,購物車是連接商品瀏覽與下單支付的關鍵環節,需要從功能、性能、兼容性、安全性等多維度進行測試。以下是購物車功能的測試用例設計: 一、功能測試 1. 商品添加到購物車 - 未登錄狀態下,添加商品到購物車(…

Linux --- 常見的基本指令

一. 前言本篇博客使用的 Linux 操作系統是 centos ,用來學習Linux 的 Linux 系統的內核版本和系統架構信息版本如下所示:上圖的主要結構為:主版本號-次版本號 修正次數,3.10.0 是操作系統的主版本號;當我們在維護一段L…

微信小程序 -開發郵箱注冊驗證功能

一、前端驗證:正則表達式與插件結合正則表達式設計 使用通用郵箱格式校驗正則,并允許中文域名(如.中國): const emailReg /^[a-zA-Z0-9._%-][a-zA-Z0-9-](?:\.[a-zA-Z0-9-])*\.[a-zA-Z]{2,}(?:\.[a-zA-Z]{2})?$/i;…

docker 部署 code-server

docker 部署 code-servercode-serverError response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headersdocker 配置正確步驟 阿里云源permission de…

網絡編程專題:從源碼解析網絡編程常用方法(基于6.16.3內核)

前言 本文是因為作者在研究下面這個代碼時發現的問題: int main() {// 1. 創建 IPv4 專用地址結構體 sockaddr_instruct sockaddr_in ipv4_addr;memset(&ipv4_addr, 0, sizeof(ipv4_addr)); // 初始化清零// 2. 填充 IPv4 專屬信息ipv4_addr.sin_family AF_IN…

2025年數字公共治理專業重點學什么內容?(詳細指南)

數字公共治理作為一個新興的跨學科領域,近年來受到越來越多高校和學生的關注。這個專業融合了多個學科的知識體系,旨在培養掌握現代治理理念和技術應用能力的復合型人才。對于在校大學生而言,了解這一專業的學習內容和發展方向,有…

一招解決 win 下 終端打印中文亂碼問題

適合所有終端 cmd powershell git bash, 原理:修改電腦的區域設置,勾選使用 UTF-8 1.電腦搜索 區域, 打開區域設置2. 打開相關設置3. 點擊更改 日期、時間或數字格式4. 選則管理-點擊更改系統區域設置,在彈出框中勾選 …

Elasticsearch面試精講 Day 13:索引生命周期管理ILM

【Elasticsearch面試精講 Day 13】索引生命周期管理ILM 在“Elasticsearch面試精講”系列的第13天,我們將深入探討 索引生命周期管理(Index Lifecycle Management, ILM) 這一核心運維機制。作為大規模日志、監控和時序數據場景下的必備功能&…