Opencv實(shí)現(xiàn)傾斜圖片轉(zhuǎn)正示例
今天是我們來(lái)玩一個(gè)釘子。通過(guò)一個(gè)釘子來(lái)學(xué)習(xí)一個(gè)opencv中的一個(gè)函數(shù),這個(gè)函數(shù)我網(wǎng)上也有搜過(guò),不過(guò)遺憾的是,各路好手都是寫(xiě)的是有點(diǎn)不堪入目,現(xiàn)在這個(gè)學(xué)習(xí)氛圍是越來(lái)越差了,很多人都直接復(fù)制粘貼別人的東西,自己也沒(méi)有理解,也沒(méi)有辨別是非的能力,所謂的拿來(lái)主義有時(shí)候真的是要不得的。知其然也要知其所以然。所以你很多時(shí)候遇到問(wèn)題去網(wǎng)上搜索的時(shí)候,你會(huì)發(fā)現(xiàn)瀏覽器上面一排網(wǎng)頁(yè),好多內(nèi)容都是相同,甚至是錯(cuò)的,這樣很不好。
閑話(huà)不多說(shuō),我們今天通過(guò)一個(gè)實(shí)例來(lái),講解一個(gè)網(wǎng)上很多人都沒(méi)搞清楚的函數(shù)cv2.minAreaRect()
我們用到圖片
我們要做的事情是將這個(gè)釘子轉(zhuǎn)成水平放心放置,然后摳出釘子的區(qū)域,就像下面這個(gè)樣子
實(shí)現(xiàn)步驟:
1.灰度化+二值化,效果圖如下
2.找輪廓,cv2.findcounters(),這樣的圖我們肯定會(huì)找到很多輪廓,所以我們可以通過(guò)面積來(lái)篩選出自己想要的那個(gè)輪廓,這里我們選擇最大的輪廓,也就是釘子的輪廓,看看效果(紅線(xiàn)就是哦我們找到的輪廓點(diǎn)然后連接起來(lái)的)
3.找這個(gè)輪廓的最小外接矩形(帶角度),這個(gè)就是最關(guān)鍵的了,也就是我們開(kāi)頭提到的cv2.minAreaRect(),我們要對(duì)他的返回值了如執(zhí)掌。先看看效果呢(藍(lán)線(xiàn)就是我們找到的最小外接矩形)
這個(gè)時(shí)候你會(huì)說(shuō),這有什么難的,我們來(lái)細(xì)細(xì)看一下,cv2.minAreaRect()的返回值是什么
box= cv2.minAreaRect(counter) print(box)
我們看看這個(gè)返回值是一個(gè)元組
((257.3854675292969, 292.03851318359375), (454.5963439941406, 140.96072387695312), 48.21548080444336)
元組的第一個(gè)元素是這個(gè)最小外接矩形的中心點(diǎn)坐標(biāo)
元組的第二個(gè)元素是也是一個(gè)元組,這個(gè)元組是最小外接矩形的兩個(gè)邊長(zhǎng)(注意是兩個(gè)邊長(zhǎng),并不是寬高),這個(gè)時(shí)候你就會(huì)問(wèn)了,這有什么區(qū)別,看上去是沒(méi)什么區(qū)別,其實(shí)是由返回順序的,有的時(shí)候長(zhǎng)的那條邊在這個(gè)元組的第一個(gè)元素位置,有的時(shí)候長(zhǎng)的那條邊在這個(gè)元組的第二個(gè)元素位置。不信我在給你看一個(gè)返回值
((290.1945495605469, 256.9798889160156), (140.9435577392578, 460.39862060546875), 49.1729850769043)
元組的第三個(gè)元素是一個(gè)浮點(diǎn)數(shù),這個(gè)浮點(diǎn)數(shù)也就是這個(gè)外接矩形的角度,那么,這個(gè)角度又是哪個(gè)邊的與X軸的角度呢?答案是要根據(jù)第二個(gè)元組的值長(zhǎng)短邊的順序來(lái)決定的,這個(gè)角度始終是第二元組中第一個(gè)元素對(duì)應(yīng)的那條邊和x的夾角。而且這個(gè)角度永遠(yuǎn)是大于0的。網(wǎng)上有人說(shuō)是-90-90°,說(shuō)實(shí)話(huà),經(jīng)過(guò)測(cè)試,我們見(jiàn)到負(fù)角度的,那些人可能試都沒(méi)試吧。也就是這個(gè)角度。
我想我已經(jīng)說(shuō)明白了
4.根據(jù)得到的中心點(diǎn)和角度以及第二個(gè)元組的值的大小就可以開(kāi)始旋轉(zhuǎn)了
值得注意的是,opencv中旋轉(zhuǎn)是逆時(shí)針旋轉(zhuǎn),所以在旋轉(zhuǎn)的時(shí)候要注意旋轉(zhuǎn)的角度,看看效果
5.有中心點(diǎn)和兩條邊長(zhǎng)的大小,我們就可以開(kāi)始摳圖了,看看效果
至此Mission accomplished。
我們上代碼吧
# -*- coding: utf-8 -*- # @Time : 2022/7/25 15:51 # @Author : guligedong import cv2 import os import numpy as np base_folder = r'F:\mvtec_anomaly_detection\screw\test\good' for i in os.listdir(base_folder): img_path = os.path.join(base_folder, i) if img_path.split('.')[-1] == 'db': continue print(img_path) img = cv2.imread(img_path) img = cv2.resize(img,(512,512)) img_h,img_w = img.shape[:2] gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _,bi_img = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY_INV) counters,_ = cv2.findContours(bi_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) for index,counter in enumerate(counters): if cv2.contourArea(counter) > 10000 : cv2.drawContours(img,counters,index,(0,0,255),1) box= cv2.minAreaRect(counter) print(box) boxs= cv2.boxPoints(box) boxs = np.int0([boxs]) print(boxs) cv2.polylines(img, boxs, isClosed=True, color=(255, 125, 125), thickness=1) cv2.imshow('img', img) # cv2.waitKey() center_x,center_y = int(box[0][0]),int(box[0][1]) lenth1, lenth2 = int(box[1][0]), int(box[1][1]) print(lenth1, lenth2) angle = box[2] print(angle) if lenth1 > lenth2: angle = angle else: angle = -(90 - angle) rotate_matrix = cv2.getRotationMatrix2D(center=(center_x,center_y),angle=angle,scale=1) rotated_image = cv2.warpAffine(src=img, M=rotate_matrix, dsize=(img_w, img_h)) cv2.imshow('Rotated image', rotated_image) y_start = center_y - min(lenth1, lenth2) // 2 if center_y - min(lenth1, lenth2) // 2 > 0 else 0 y_end = center_y + min(lenth1, lenth2) // 2 if center_y + min(lenth1, lenth2) // 2 < img_h else img_h x_start = center_x - max(lenth1, lenth2) // 2 if center_x - max(lenth1, lenth2) // 2 >0 else 0 x_end = center_x + max(lenth1, lenth2) // 2 if center_x + max(lenth1, lenth2) // 2 <img_w else img_w crop_image = rotated_image[y_start:y_end,x_start:x_end] cv2.imshow('crop_image', crop_image) cv2.waitKey()
這個(gè)數(shù)據(jù)是mvtec_anomaly_detection數(shù)據(jù)集中的釘子的數(shù)據(jù)集,大家可以網(wǎng)上找資源試一試小效果,關(guān)鍵是要自己理解這個(gè)邏輯。
到此這篇關(guān)于Opencv實(shí)現(xiàn)傾斜圖片轉(zhuǎn)正示例的文章就介紹到這了,更多相關(guān)Opencv 傾斜圖片轉(zhuǎn)正內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python縮進(jìn)長(zhǎng)度是否統(tǒng)一
在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于python縮進(jìn)長(zhǎng)度是否統(tǒng)一的相關(guān)知識(shí)點(diǎn),需要的朋友們可以學(xué)習(xí)下。2020-08-08Python實(shí)現(xiàn)把json格式轉(zhuǎn)換成文本或sql文件
這篇文章主要介紹了Python實(shí)現(xiàn)把json格式轉(zhuǎn)換成文本或sql文件,本文直接給出代碼實(shí)例,需要的朋友可以參考下2015-07-07Python OpenCV機(jī)器學(xué)習(xí)之圖像識(shí)別詳解
OpenCV中也提供了一些機(jī)器學(xué)習(xí)的方法,例如DNN等。本文將為大家詳細(xì)介紹一下OpenCV中利用機(jī)器學(xué)習(xí)實(shí)現(xiàn)的一些圖片識(shí)別功能:人臉識(shí)別、車(chē)牌識(shí)別等,感興趣的可以了解一下2022-01-01python中matplotlib的用法及繪制簡(jiǎn)單圖形詳解
這篇文章主要給大家介紹了關(guān)于python中matplotlib的用法及繪制簡(jiǎn)單圖形的相關(guān)資料,matplotlib是python中用于繪制各種圖像的模塊,功能十分強(qiáng)大,通常與pandas模塊搭配使用,可以生成各種樣視的圖片,用于數(shù)據(jù)的分析和展示,需要的朋友可以參考下2024-03-03python數(shù)據(jù)挖掘使用Evidently創(chuàng)建機(jī)器學(xué)習(xí)模型儀表板
在本文中,我們將探索 Evidently 并創(chuàng)建交互式報(bào)告/儀表板。有需要的朋友歡迎大家收藏學(xué)習(xí),希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2021-11-11