編程實戰(4)——python識別影像中的坐標點并保存坐標資料
文章目錄
- 編程實戰(4)——python識別影像中的坐標點并保存坐標資料
- 綜述
- 代碼思路
- 庫的安裝
- 圖片預處理
- 影像細化
- 影像二極化
- 提取資料
- 結果展示和保存
- matplotlib重繪
- 寫入excel
- 全部原始碼
綜述
最近因為美賽的需求,需要在提取一些賽道的路線圖和地形圖中的準確資料,因此對這方面做了一些了解,在研究的程序中,我發現網上的很多相關的帖子并不是很靠譜,不是報錯就是沒有說清楚一些函式的功能,所以我打算寫一篇比較詳細的文章,
本文主要講述利用python介面的opencv來完成影像識別和資訊提取并重新繪制、保存為excel資料的詳細程序與思路,適合opencv方面的小白觀看(需要一定的numpy和matplotlib基礎),如有一些疏漏,請大佬們指出~
代碼思路
我會跟著我代碼的思路逐一講解每一步的思路和函式的一些解釋;
總體思路如下:
- 第一:圖片預處理,讓影像二極化;
- 第二:提取圖片資料
- 第三步:資料整理與保存
庫的安裝
這里一共用了三個庫
import cv2
import numpy as np
import matplotlib.pyplot as plt
numpy和matplotlib的安裝都比較常規,但是cv2的安裝不是常規的pip install cv2,是opencv-python,國內鏡像下載地址:
pip3 install -i https://mirrors.aliyun.com/pypi/simple/ opencv-python
圖片預處理
img = cv2.imread('你的圖片路徑')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
首先打開圖片,然后對圖片做一個hsv灰度圖的處理,因為我們常規的圖片像素點都是rbg空間模式的,我們需要先轉化為hsv顏色空間模式(沒見過這個影像格式的可以百度一下),以便后面的影像二值化處理;

上面是我用到的影像,這是東京奧運會公路自行車比賽的路線圖,我們要做的就是提取路線像素并坐標化;
影像細化
如果說要處理的影像的線條很粗,那就會影響后面的識別程序,需要先進行影像細化;如果原本圖的線條就很細(比如我的),那就可以跳過這一步,
影像細化我是直接參考一個博客的代碼的,這里做一個參考:影像細化,骨架提取
寫的相當棒,大家可以參考一下,
影像二極化
這里我用到了一個cv庫中的inRange函式,這個函式的功能是對讀入的影像檔案(即函式第一個引數)做一個二值化處理,
總的來說就是我們需要規定兩個閾值lowerb和upperb,大于upperb和小于lowerb的影像像素點均會被轉化為0(即黑色),在這個范圍內的點被轉化為255(白色);
low_hsv = np.array([0, 0, 221])
high_hsv = np.array([180, 30, 255])
mask = cv2.inRange(hsv, lowerb=low_hsv, upperb=high_hsv)
我們再來詳細的講一下這兩個閾值,如果了解hsv顏色空間的話,很容易可以發現代碼的前兩行就是hsv顏色空間的兩個值,numpy.array函式里面的引數剛好就是色調、飽和度和明度值,因為inRange函式的需要,我們要轉化成numpy格式的陣列,我這里需要提取所有黑色的坐標,所以設的是黑色與白色的閾值,大家可以根據自己的需求調整顏色閾值,
閾值參考:HSV基本顏色分量范圍
這里的mask,就是我們需要提取資料的影像了~
提取資料
為了幫助大家理解,我們先列印看一下mask的具體情況:
print(len(mask))
print(len(mask[0]))
for i in range(len(mask)):
print(mask[i])
輸出:
654
1024
[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
...
[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
可以看到影像是1024*654的,還有每一行的像素點都是一個numpy陣列(numpy陣列列印出來元素之間是沒有用逗號間隔的),之前24位的hsv圖,變成了8位的灰度圖(每一項只有一個資料,而不是三個陣列成的array);
我們要做的是要知道每一個黑色的像素點的橫縱坐標,即在mask這個像素矩陣中,獲取值為0的行號和列號,
方法也很簡單,直接遍歷每一個像素,找到值為0的像素點,存取列號和行號即可;
list_y = []
list_x = []
for i in range(len(mask)):
#print(mask[i])
xmax = []
for j in range(len(mask[i])):
if mask[i][j] == 0:
#print(mask[i][j],j,i)
list_x.append(j)
list_y.append(len(mask)-i)
這里需要注意,很多影像存盤資料是從下往上存盤的,所以我們在獲取列號的時候,需要用影像的高度減去mask的列號,才是真正的列號,
結果展示和保存
matplotlib重繪
檢驗一下我們獲取的影像資料,注意這里需要用散點圖模式繪圖,不然會有不太好的后果,,,
plt.plot(list_x, list_y, 'o', color='r')
plt.show()
結果如下:

可以發現提取效果還是不錯的~~
寫入excel
這一部分的說明直接放到注釋里面了
import xlwt
wb = xlwt.Workbook()
ws = wb.add_sheet('sheet1') # 添加一個表
ws.write(0, 0, "x") # 寫入資料,3個引數分別為行號,列號,和內容
ws.write(0, 1, "y")
i = 1 #指標,每寫一個資料,向下移動寫指標一行
for x in list_x:
ws.write(i, 0, x)
i += 1
j = 1
for y in list_y:
ws.write(j, 1, y)
j += 1
wb.save('1111.xls')
可以看到資料已經保存進excel里面了
這一次提取其實還有一個小問題,就是相同的橫坐標下還是有多個對應該橫坐標的點,如果需要做函式分析之類的操作,我們可以直接用excel作按值分組然后去每組的特定值即可,最大值,平均值均可,看個人需求,
全部原始碼
import cv2
import numpy as np
import matplotlib.pyplot as plt
import xlwt
img = cv2.imread('3.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
low_hsv = np.array([0, 0, 221])
high_hsv = np.array([180, 30, 255])
mask = cv2.inRange(hsv, lowerb=low_hsv, upperb=high_hsv)
print(len(mask))
print(len(mask[0]))
list_y = []
list_x = []
for i in range(len(mask)):
print(mask[i])
xmax = []
for j in range(len(mask[i])):
if mask[i][j] == 0:
print(mask[i][j],j,i)
list_x.append(j)
list_y.append(len(mask)-i)
plt.plot(list_x, list_y, 'o', color='r')
plt.show()
wb = xlwt.Workbook()
ws = wb.add_sheet('sheet1')
ws.write(0, 0, "x")
ws.write(0, 1, "y")
i = 1
for x in list_x:
ws.write(i, 0, x)
i += 1
j = 1
for y in list_y:
ws.write(j, 1, y)
j += 1
wb.save('1111.xls')
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/433224.html
標籤:AI
上一篇:機器學習(十一) 遷移學習
