付費限定

[OpenCV應用][Python]利用SIFT得取圖片物件旋轉角度,並旋轉回正常角度

更新於 發佈於 閱讀時間約 39 分鐘

利用OPENCV,實現SIFT應用,尋找圖片中物件的旋轉角度

前言

SIFT的介紹,維基百科寫的就會比我清楚很多,就不在贅述
維基百科連結

本文介紹主要提出SIFT提取關鍵角點的座標,由此算出物件的旋轉角度

程式功能介紹 : 導入待檢測圖及樣本圖,則會依照樣本圖中的物件為基準,算出待檢圖實際旋轉的角度

實驗方法:找兩張一模一樣的圖,待檢測圖先旋轉90度,樣本圖為此原狀,利用此程式算出旋轉角度並轉正存圖

實驗結果:算出旋轉角度:90.01496444740344 度

raw-image

結果圖

org_img : 待檢測圖,故意旋轉90度

temp_img : 樣本圖,使待檢測圖有個檢測的基準result_img : 算出旋轉角度後,在將待檢測圖旋轉存入

raw-image

程式碼及圖片連結


程式碼範例解說

import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.pyplot as plt

#這是一個 FeatureMatching 類別的初始化方法,用來進行特徵匹配的準備工作。
class FeatureMatching:
def __init__(self, query_image='data/query.jpg'):
self.sift = cv2.SIFT_create()
self.img_query = cv2.imread(query_image, 0)
#讀取temp
if self.img_query is None:
print("Could not find train image " + query_image)
raise SystemExit
self.shape_query = self.img_query.shape[:2] # 對應的是y x
# detectAndCompute 返回關鍵點,跟描述符,供後續特徵匹配做使用
self.key_query, self.desc_query = self.sift.detectAndCompute(self.img_query, None)
FLANN_INDEX_KDTREE = 0
#FLANN 特徵匹配器
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) #使用K-D Tree算法進行最近鄰搜索,trees=5 表示構建K-D Tree時使用的樹的數量。
search_params = dict(checks=50) #checks=50 表示進行搜索時,每次搜索最近鄰時檢查的節點數量。
self.flann = cv2.FlannBasedMatcher(index_params, search_params)

#抽取特徵
def _extract_features(self, frame):
sift = cv2.SIFT_create()
key_train, desc_train = sift.detectAndCompute(frame, None)
return key_train, desc_train
#匹配特徵
def _match_features(self, desc_frame):
matches = self.flann.knnMatch(self.desc_query, desc_frame, k=2)
good_matches = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good_matches.append(m)
return good_matches
def _detect_corner_points(self, key_frame, good_matches):
src_points = np.float32([self.key_query[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2) #是 query 圖像中好的匹配點對應的特徵點坐標
dst_points = np.float32([key_frame[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2) #是 frame 圖像中好的匹配點對應的特徵點坐標
H, mask = cv2.findHomography(src_points, dst_points, cv2.RANSAC, 5.0) #計算兩組對應點之間的單應變換,這裡用於計算 query 到 frame 的變換
matchesMask = mask.ravel().tolist()
h, w = self.img_query.shape[:2]
src_corners = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2) #是 query 圖像的四個角點的坐標,這裡是左上、左下、右下和右上。這些點用於形成一個矩形,後面會被變換到 frame 圖像上
dst_corners = cv2.perspectiveTransform(src_corners, H) #得到在 frame 圖像上的角點坐標
return dst_corners, H, matchesMask

def _frontal_keypoints(self, frame, H):
Hinv = np.linalg.inv(H) #計算單應性矩陣 H 的逆矩陣,得到透視變換的反變換矩陣。
# 從單應性矩陣 H 中提取旋轉部分
print(f'Hinv"{Hinv}')
rotation_matrix = Hinv[:2, :2] # 從逆變換矩陣中提取旋轉部分,這是一個 2x2 的矩陣。
# 計算旋轉角度(以度為單位)
rotation_angle = np.arctan2(rotation_matrix[1, 0], rotation_matrix[0, 0]) * (180 / np.pi) #使用反正切函數 arctan2 計算旋轉角度
print(f"旋轉角度:{rotation_angle} 度")
dst_size = frame.shape[:2]
img_front = cv2.warpPerspective(frame, Hinv, dst_size, flags=cv2.INTER_LINEAR) #應用反變換,對輸入圖像進行逆透視變換,獲得正面視角的圖像。
return img_front , rotation_angle

def match(self, frame):
img_train = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
shape_train = img_train.shape[:2]
key_train, desc_train = self._extract_features(img_train)
good_matches = self._match_features(desc_train)
if len(good_matches) < 4:
self.num_frames_no_success += 1
return False, frame
# drawMatchesKnn 函數在兩張圖像之間繪製特徵匹配的結果, self.img_query:即模板圖像 img_train即待匹配的圖像
img_match = cv2.drawMatchesKnn(self.img_query, self.key_query, img_train, key_train, [good_matches], None,
flags=2)
plt.imshow(img_match) #繪製匹配的結果
plt.show()
#算出變換後的角點座標,單映矩陣,matchesMask被用來只繪製模型的內點
dst_corners, Hinv, _ = self._detect_corner_points(key_train, good_matches)
dst_ravel = dst_corners.ravel()
#檢查角點座標是否超出範圍
dst_ravel_Spec = 1500 #可允許範圍
if (dst_ravel > shape_train[0] + dst_ravel_Spec).any() and (dst_ravel > -dst_ravel_Spec).any() \
and (dst_ravel > shape_train[1] + dst_ravel_Spec).any():
self.num_frames_no_success += 1
print('角點離圖片太遠')
return False, frame
#轉換成正面視角
img_front, img_angle = self._frontal_keypoints(frame, Hinv)
return True, img_front , img_angle

def rotate_image(image, angle):
# 取得影像中心點坐標
center = tuple(np.array(image.shape[1::-1]) / 2)
# 設定旋轉矩陣
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
# 進行影像旋轉
rotated_image = cv2.warpAffine(image, rotation_matrix, image.shape[1::-1], flags=cv2.INTER_LINEAR)
# 將旋轉後的影像存儲
output_path = "F:/python/opencv/Result.jpg"
cv2.imwrite(output_path, rotated_image)
return rotated_image

#載入原圖
img_train = cv2.imread('rotation.jpg')
#載入樣本圖
temp_img = cv2.imread('temp_org.jpg')
matching = FeatureMatching(query_image='temp_org.jpg')

flag , img_front, img_angle = matching.match(img_train)
#算出的角度需要 換方向 加負號
Result_img = rotate_image(img_train , -img_angle)

# 將結果轉換回彩色圖
img_train = cv2.cvtColor(img_train, cv2.COLOR_BGR2RGB)
temp_img = cv2.cvtColor(temp_img, cv2.COLOR_BGR2RGB)
Result_img = cv2.cvtColor(Result_img, cv2.COLOR_BGR2RGB)
# 顯示原始圖片和結果
plt.subplot(1, 3, 1), plt.imshow(img_train), plt.title('org_img'), plt.axis('off')
plt.subplot(1, 3, 2), plt.imshow(temp_img), plt.title('temp_img'), plt.axis('off')
plt.subplot(1, 3, 3), plt.imshow(Result_img), plt.title('result_img'), plt.axis('off')
plt.show()

函式功能解說

FeatureMatching :特徵匹配的類別,初始化方法__init__用來進行特徵匹配的準備工作,包括使用SIFT算法檢測並計算特徵點,使用FLANN特徵匹配器進行特徵匹配等。

_extract_features 方法:抽取圖片的特徵,這裡使用SIFT算法。

_match_features 方法:進行特徵匹配,這裡使用FLANN特徵匹配器。

_detect_corner_points 方法:檢測匹配到的角點,計算透視變換矩陣。

_frontal_keypoints 方法:根據透視變換矩陣,將圖片轉換成正面視角。

match 方法:實際進行特徵匹配,並根據透視變換將圖片轉換成正面視角。

在主程式中,載入原圖、樣本圖,並使用 FeatureMatching 進行特徵匹配。接著,使用 _frontal_keypoints 將匹配的圖片轉換成正面視角,然後使用 rotate_image 方法進行影像旋轉,最後顯示原始圖片、樣本圖片和結果圖片。

rotate_image 方法:這是一個影像旋轉的函式,使用 OpenCV 的 cv2.getRotationMatrix2D cv2.warpAffine 函數進行旋轉。

FeatureMatching 類別初始化 (__init__ 方法)

def __init__(self, query_image='data/query.jpg'):
# 初始化 SIFT 物件
self.sift = cv2.SIFT_create()
# 讀取模板圖片(query_image)
self.img_query = cv2.imread(query_image, 0)
if self.img_query is None:
print("Could not find train image " + query_image)
raise SystemExit
# 取得模板圖片的形狀(高度和寬度)
self.shape_query = self.img_query.shape[:2]
# 用 SIFT 算法提取模板圖片的關鍵點和描述符
self.key_query, self.desc_query = self.sift.detectAndCompute(self.img_query, None)
# 使用 FLANN 特徵匹配器
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
self.flann = cv2.FlannBasedMatcher(index_params, search_params)

在 __init__ 方法中,這是 FeatureMatching 類別的初始化部分。以下是詳細說明:

  1. self.sift = cv2.SIFT_create(): 創建了一個 SIFT 物件,用於後續的特徵提取。
  2. self.img_query = cv2.imread(query_image, 0): 讀取指定路徑的模板圖片(query_image),並以灰度模式(0 表示灰度)讀入。
  3. if self.img_query is None: ...: 檢查是否成功讀取模板圖片,如果未成功,則輸出錯誤信息並退出程式。
  4. self.shape_query = self.img_query.shape[:2]: 取得模板圖片的形狀,即高度和寬度,存儲在 self.shape_query 中。
  5. self.key_query, self.desc_query = self.sift.detectAndCompute(self.img_query, None): 使用 SIFT 算法檢測並計算模板圖片的關鍵點和描述符。

self.key_query:存儲關鍵點

以行動支持創作者!付費即可解鎖
本篇內容共 15753 字、3 則留言,僅發佈於[Python][OpenCV]學習心得筆記你目前無法檢視以下內容,可能因為尚未登入,或沒有該房間的查看權限。
留言
avatar-img
留言分享你的想法!
螃蟹_crab-avatar-img
發文者
2024/02/07
[OpenCV基礎][Python]warpPerspective透視變換提及了這篇文章,趕快過去看看吧!
avatar-img
螃蟹_crab的沙龍
147會員
282內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。 興趣是攝影,踏青,探索未知領域。 人生就是不斷的挑戰及自我認清,希望老了躺在床上不會後悔自己什麼都沒做。
螃蟹_crab的沙龍的其他內容
2025/04/01
1. 概述 在光學字符識別(OCR)過程中,常見的問題之一是「斷字」,即原本應為一個完整字符的部分被錯誤地分割成兩個或多個獨立的字符。這通常發生在掃描文件、圖像降噪或影像二值化處理後。本篇文章將介紹一種基於 骨架化端點距離分析 的斷字檢測方法,並提供完整的 Python 實作。 2. 斷字檢測的
Thumbnail
2025/04/01
1. 概述 在光學字符識別(OCR)過程中,常見的問題之一是「斷字」,即原本應為一個完整字符的部分被錯誤地分割成兩個或多個獨立的字符。這通常發生在掃描文件、圖像降噪或影像二值化處理後。本篇文章將介紹一種基於 骨架化端點距離分析 的斷字檢測方法,並提供完整的 Python 實作。 2. 斷字檢測的
Thumbnail
2025/03/13
本教學將介紹如何使用 OpenCV 來檢測螺絲的鎖附間距,並提供完整的 Python 程式碼來實作這項功能。 🔹 1. 設計目標 使用二值化處理與形態學運算來強化影像 計算螺絲之間的間距 視覺化結果,標記最大間距並顯示數值 🔹 2. 測試用螺絲影像 🔹 3.
Thumbnail
2025/03/13
本教學將介紹如何使用 OpenCV 來檢測螺絲的鎖附間距,並提供完整的 Python 程式碼來實作這項功能。 🔹 1. 設計目標 使用二值化處理與形態學運算來強化影像 計算螺絲之間的間距 視覺化結果,標記最大間距並顯示數值 🔹 2. 測試用螺絲影像 🔹 3.
Thumbnail
2025/01/18
我們將學習如何使用 Python 和 OpenCV 實現圖像的主色提取與重新著色。 以下的程式碼展示了如何通過 KMeans 聚類演算法分析圖像,提取 HSV 色彩空間中的主色,並將圖像重新著色,提取想偵測的物件的顏色。 在官網案例,實作為RGB色彩空間,但如果套用HSV色彩空間則會因為H色
Thumbnail
2025/01/18
我們將學習如何使用 Python 和 OpenCV 實現圖像的主色提取與重新著色。 以下的程式碼展示了如何通過 KMeans 聚類演算法分析圖像,提取 HSV 色彩空間中的主色,並將圖像重新著色,提取想偵測的物件的顏色。 在官網案例,實作為RGB色彩空間,但如果套用HSV色彩空間則會因為H色
Thumbnail
看更多
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
本文將說明如何去辨識出圖片文字​位置及高寬。
Thumbnail
本文將說明如何去辨識出圖片文字​位置及高寬。
Thumbnail
[OpenCV應用][Python]找出圖像中的四個方位的邊緣點求出寬高 呈上篇應用Numpy找到的座標點,那我們如何捨棄掉差異過大的座標點呢? 可能圖像物件邊緣不佳,採樣就會差異過大,造成計算出的寬高是不準確的。 遇到這種狀況,就可以使用下方的程式範例來篩選座標點。 為求方便,此範例跟圖
Thumbnail
[OpenCV應用][Python]找出圖像中的四個方位的邊緣點求出寬高 呈上篇應用Numpy找到的座標點,那我們如何捨棄掉差異過大的座標點呢? 可能圖像物件邊緣不佳,採樣就會差異過大,造成計算出的寬高是不準確的。 遇到這種狀況,就可以使用下方的程式範例來篩選座標點。 為求方便,此範例跟圖
Thumbnail
觀看本文將可以學習到如何利用Numpy求得物件的邊緣點,及算出物件的寬跟高。 有詳細的程式邏輯說明,及各函式用法說明。 綠點及紅點則是採樣到的邊界點,比較粗的點是偵測到的最大值 完整程式碼 import cv2 import numpy as np import matplotl
Thumbnail
觀看本文將可以學習到如何利用Numpy求得物件的邊緣點,及算出物件的寬跟高。 有詳細的程式邏輯說明,及各函式用法說明。 綠點及紅點則是採樣到的邊界點,比較粗的點是偵測到的最大值 完整程式碼 import cv2 import numpy as np import matplotl
Thumbnail
直方圖是對圖像中像素強度分布的圖形表示。通過分析直方圖,我們可以獲得有關圖像對比度、亮度和色彩分佈的有用信息。
Thumbnail
直方圖是對圖像中像素強度分布的圖形表示。通過分析直方圖,我們可以獲得有關圖像對比度、亮度和色彩分佈的有用信息。
Thumbnail
廢話不多說,先上成果圖。 成果圖 主要實現方法 1.灰階後利用cv2.Canny找物體的邊緣 2.找物件相對應的直線cv2.HoughLines 3.分類為橫向和垂直的直線角度,求得相對於物件的旋轉角度 4.根據算出的相對應旋轉角度將物件轉正
Thumbnail
廢話不多說,先上成果圖。 成果圖 主要實現方法 1.灰階後利用cv2.Canny找物體的邊緣 2.找物件相對應的直線cv2.HoughLines 3.分類為橫向和垂直的直線角度,求得相對於物件的旋轉角度 4.根據算出的相對應旋轉角度將物件轉正
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
本文將介紹影像的基本操作包括:影像的讀取、顯示、保存,以及一些常見的操作如裁剪、旋轉、縮放等。 語法介紹 讀取影像: cv2.imread函數的參數是影像的檔案路徑。讀取後的影像以NumPy的ndarray形式表示。
Thumbnail
大部分在求物件的寬度及高度,都會想到用OpenCV的findContours函式來做,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度 [OpenCV應用][Python]利用findContours找出物件邊界框求出寬度及高度 本文將用不同的方法,利用Numpy
Thumbnail
大部分在求物件的寬度及高度,都會想到用OpenCV的findContours函式來做,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度 [OpenCV應用][Python]利用findContours找出物件邊界框求出寬度及高度 本文將用不同的方法,利用Numpy
Thumbnail
本文將利用OpenCV的findContours函式,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度。 一般來說,我們在進行輪廓檢測時,會先進行圖像二值化,將對象轉換為白色,背景為黑色。這樣,在找到輪廓後,輪廓的點就會以白色表示,背景為黑色。 結果圖 從圖中綠色框
Thumbnail
本文將利用OpenCV的findContours函式,從找到的輪廓中來計算物件的面積,周長,邊界框等屬性,從而得到物體的寬度與高度。 一般來說,我們在進行輪廓檢測時,會先進行圖像二值化,將對象轉換為白色,背景為黑色。這樣,在找到輪廓後,輪廓的點就會以白色表示,背景為黑色。 結果圖 從圖中綠色框
Thumbnail
利用OPENCV,實現SIFT應用,尋找圖片中物件的旋轉角度 本文介紹主要提出SIFT提取關鍵角點的座標,由此算出物件的旋轉角度 程式功能介紹 : 導入待檢測圖及樣本圖,則會依照樣本圖中的物件為基準
Thumbnail
利用OPENCV,實現SIFT應用,尋找圖片中物件的旋轉角度 本文介紹主要提出SIFT提取關鍵角點的座標,由此算出物件的旋轉角度 程式功能介紹 : 導入待檢測圖及樣本圖,則會依照樣本圖中的物件為基準
Thumbnail
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉
Thumbnail
[影像處理_OpenCV Python]使用Python撰寫影像處理功能,圖片遮罩或濾除掉不要的地方,旋轉圖片 以下範例將呈現影像處理三種不同的應用: 遮罩的實現 濾除 旋轉
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News