opencv获取图片像素坐标_利用OpenCV从图片中提取矩形并标注坐标(室内平面地图)(一)
?某城市會展中心室內地圖
背景
一名室內設計師的日常工作從設計一張會展地圖開始。常常有這樣的場景:劃分除規范的展位后,進入銷售階段,頻繁的需要修改這張地圖,如展示拆分、合并、換位置、標記已交易。
問題
從上圖中標記色塊的是有效展位,經過設計師設計確定了坐標、尺寸、編號(不重要)。需要解決的是從圖片中提取出色塊的精確位置和尺寸,然后通過html5展示到頁面上;后續修改操作(合并、拆分等)完全通過頁面在完成。
提取矩形頂點坐標
矩形的檢測主要是提取邊緣,圖中色塊部分明顯有別于周圍顏色(指灰度),我們可以將圖片灰度,將展位部分與過道部分明顯的分別開,對后續做邊緣計算就非常有幫助。
檢測矩形并提取坐標需要對圖像進行預處理、邊緣檢測、提取輪廓、檢測凸包(或者最小矩形)、頂點獲取。
圖片預處理
由于圖片的特性,只要做轉灰度、中值濾波
img = cv2.imread(url)# 灰度圖,濾波gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)gray = cv2.medianBlur(gray, 15)處理后的圖片如下
處理后的圖片
邊緣檢測
# 邊緣CANNY_THRESH_1 = 90CANNY_THRESH_2 = 120edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2)edges = cv2.dilate(edges, None, iterations=3)edges = cv2.erode(edges, None, iterations=1)邊緣特征比較明顯,不同的圖片系數差別不大。當前系數效果可以使用。更細的參數沒有調整。
另外做了一些放大和腐蝕,把不需要的一些小的文字區域過濾掉了。方便過濾不需要的輪廓。
提取輪廓
# 查找輪廓contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 顯示所有輪廓mask = np.zeros(img.shape)for c in contours: # 過濾小面積 if (cv2.contourArea(c) < scale ** 2): continue cv2.drawContours(mask, [c], 0, (0, 0, 255))cv2.imshow('contours', mask)關于函數findContours介紹可以參考:https://www.cnblogs.com/yiyi20120822/p/11506970.html
提取到的輪廓
提取到的輪廓基本完整,屬于規則的圓角矩形。上圖因為彈窗渲染問題顯示不全,其實紅色的框是一個非常漂亮地閉合矩形。
這里更具不同參數可提取不同的輪廓,這里我只去了最外層。另外我需要的是規則矩形,因此不需要額外的尋找凸包-提取頂點。用一個比較單間的最小包圍矩形就能得到想要的結果。
提取矩形獲取頂點
rect = cv2.minAreaRect(cnt)box = cv2.boxPoints(rect)box = np.int0(box)# 打印box的結果,每一組四個point順時針顯示# 第一個矩形[[5350 4899] [5350 4784] [5791 4784] [5791 4899]]# 第二個矩形[[4804 4900] [4804 4785] [5247 4785] [5247 4900]]# ……結束
截止到這里,已經得到了需要的基礎數據信息。根據坐標信息即可把展位還原到頁面上。
完整代碼附上
#!/usr/bin/python3# coding:utf-8# description: 標記地圖的色塊位置# user: arik# @time: 2020/1/3 10:45import cv2import numpy as npimport log### url: 圖片地址# scale: 圖片比例,例如 3m=100px,3m是圖片的基本單元尺寸# #def get_rectangle(url, scale=100): img = cv2.imread(url) # 灰度圖,濾波 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) gray = cv2.medianBlur(gray, 15) # cv2.imshow('line', gray) # 邊緣 CANNY_THRESH_1 = 90 CANNY_THRESH_2 = 120 edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2) edges = cv2.dilate(edges, None, iterations=3) edges = cv2.erode(edges, None, iterations=1) # 查找輪廓 contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) json_res = [] # mask = np.zeros(img.shape) for c in contours: # 過濾小面積 if (cv2.contourArea(c) < scale ** 2): continue rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.int0(box) # cv2.drawContours(mask, [c], 0, (0, 0, 255)) box = key_point_2_array(box) json_res.append(box) # 輸出到文件 log.json_log(json_res) # 顯示圖片 # cv2.imshow('line', mask)### point轉數組# #def key_point_2_array(box): res = [] for p in box: res.append([p[0], p[1]]) return resif __name__ == "__main__": get_rectangle('images/origin/map1.jpg', 100) # cv2.waitKey(0) # cv2.destroyAllWindows()下一篇文章補充頁面還原問題。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的opencv获取图片像素坐标_利用OpenCV从图片中提取矩形并标注坐标(室内平面地图)(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基金是直接卖出好还是转换好?基金转换你操
- 下一篇: 【Qt】解决GDAL直接读取数据到QIm