编程实战(4)——python识别图像中的坐标点并保存坐标数据
編程實(shí)戰(zhàn)(4)——python識別圖像中的坐標(biāo)點(diǎn)并保存坐標(biāo)數(shù)據(jù)
文章目錄
- 編程實(shí)戰(zhàn)(4)——python識別圖像中的坐標(biāo)點(diǎn)并保存坐標(biāo)數(shù)據(jù)
- 綜述
- 代碼思路
- 庫的安裝
- 圖片預(yù)處理
- 圖像細(xì)化
- 圖像二極化
- 提取數(shù)據(jù)
- 結(jié)果展示和保存
- matplotlib重繪
- 寫入excel
- 全部源碼
綜述
最近因?yàn)槊蕾惖男枨?#xff0c;需要在提取一些賽道的路線圖和地形圖中的準(zhǔn)確數(shù)據(jù),因此對這方面做了一些了解。在研究的過程中,我發(fā)現(xiàn)網(wǎng)上的很多相關(guān)的帖子并不是很靠譜,不是報錯就是沒有說清楚一些函數(shù)的功能,所以我打算寫一篇比較詳細(xì)的文章。
本文主要講述利用python接口的opencv來完成圖像識別和信息提取并重新繪制、保存為excel數(shù)據(jù)的詳細(xì)過程與思路,適合opencv方面的小白觀看(需要一定的numpy和matplotlib基礎(chǔ))。如有一些疏漏,請大佬們指出~
代碼思路
我會跟著我代碼的思路逐一講解每一步的思路和函數(shù)的一些解釋;
總體思路如下:
- 第一:圖片預(yù)處理,讓圖像二極化;
- 第二:提取圖片數(shù)據(jù)
- 第三步:數(shù)據(jù)整理與保存
庫的安裝
這里一共用了三個庫
import cv2 import numpy as np import matplotlib.pyplot as pltnumpy和matplotlib的安裝都比較常規(guī),但是cv2的安裝不是常規(guī)的pip install cv2,是opencv-python,國內(nèi)鏡像下載地址:
pip3 install -i https://mirrors.aliyun.com/pypi/simple/ opencv-python圖片預(yù)處理
img = cv2.imread('你的圖片路徑') hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)首先打開圖片,然后對圖片做一個hsv灰度圖的處理,因?yàn)槲覀兂R?guī)的圖片像素點(diǎn)都是rbg空間模式的,我們需要先轉(zhuǎn)化為hsv顏色空間模式(沒見過這個圖像格式的可以百度一下),以便后面的圖像二值化處理;
上面是我用到的圖像,這是東京奧運(yùn)會公路自行車比賽的路線圖,我們要做的就是提取路線像素并坐標(biāo)化;
圖像細(xì)化
如果說要處理的圖像的線條很粗,那就會影響后面的識別過程,需要先進(jìn)行圖像細(xì)化;如果原本圖的線條就很細(xì)(比如我的),那就可以跳過這一步。
圖像細(xì)化我是直接參考一個博客的代碼的,這里做一個引用:圖像細(xì)化,骨架提取
寫的相當(dāng)棒,大家可以參考一下。
圖像二極化
這里我用到了一個cv庫中的inRange函數(shù),這個函數(shù)的功能是對讀入的圖像文件(即函數(shù)第一個參數(shù))做一個二值化處理。
總的來說就是我們需要規(guī)定兩個閾值lowerb和upperb,大于upperb和小于lowerb的圖像像素點(diǎn)均會被轉(zhuǎn)化為0(即黑色),在這個范圍內(nèi)的點(diǎn)被轉(zhuǎn)化為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)我們再來詳細(xì)的講一下這兩個閾值,如果了解hsv顏色空間的話,很容易可以發(fā)現(xiàn)代碼的前兩行就是hsv顏色空間的兩個值,numpy.array函數(shù)里面的參數(shù)剛好就是色調(diào)、飽和度和明度值,因?yàn)閕nRange函數(shù)的需要,我們要轉(zhuǎn)化成numpy格式的數(shù)組。我這里需要提取所有黑色的坐標(biāo),所以設(shè)的是黑色與白色的閾值,大家可以根據(jù)自己的需求調(diào)整顏色閾值。
閾值參考:HSV基本顏色分量范圍
這里的mask,就是我們需要提取數(shù)據(jù)的圖像了~
提取數(shù)據(jù)
為了幫助大家理解,我們先打印看一下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的,還有每一行的像素點(diǎn)都是一個numpy數(shù)組(numpy數(shù)組打印出來元素之間是沒有用逗號間隔的),之前24位的hsv圖,變成了8位的灰度圖(每一項(xiàng)只有一個數(shù)據(jù),而不是三個數(shù)組成的array);
我們要做的是要知道每一個黑色的像素點(diǎn)的橫縱坐標(biāo),即在mask這個像素矩陣中,獲取值為0的行號和列號。
方法也很簡單,直接遍歷每一個像素,找到值為0的像素點(diǎn),存取列號和行號即可;
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)這里需要注意,很多圖像存儲數(shù)據(jù)是從下往上存儲的,所以我們在獲取列號的時候,需要用圖像的高度減去mask的列號,才是真正的列號。
結(jié)果展示和保存
matplotlib重繪
檢驗(yàn)一下我們獲取的圖像數(shù)據(jù),注意這里需要用散點(diǎn)圖模式繪圖,不然會有不太好的后果。。。
plt.plot(list_x, list_y, 'o', color='r') plt.show()結(jié)果如下:
可以發(fā)現(xiàn)提取效果還是不錯的~~
寫入excel
這一部分的說明直接放到注釋里面了
import xlwtwb = xlwt.Workbook()ws = wb.add_sheet('sheet1') # 添加一個表ws.write(0, 0, "x") # 寫入數(shù)據(jù),3個參數(shù)分別為行號,列號,和內(nèi)容 ws.write(0, 1, "y")i = 1 #指針,每寫一個數(shù)據(jù),向下移動寫指針一行 for x in list_x:ws.write(i, 0, x)i += 1j = 1 for y in list_y:ws.write(j, 1, y)j += 1wb.save('1111.xls')可以看到數(shù)據(jù)已經(jīng)保存進(jìn)excel里面了
這一次提取其實(shí)還有一個小問題,就是相同的橫坐標(biāo)下還是有多個對應(yīng)該橫坐標(biāo)的點(diǎn),如果需要做函數(shù)分析之類的操作,我們可以直接用excel作按值分組然后去每組的特定值即可,最大值,平均值均可,看個人需求。
全部源碼
import cv2 import numpy as np import matplotlib.pyplot as plt import xlwtimg = 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 += 1j = 1 for y in list_y:ws.write(j, 1, y)j += 1wb.save('1111.xls')總結(jié)
以上是生活随笔為你收集整理的编程实战(4)——python识别图像中的坐标点并保存坐标数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样删除Word文档的强制性回车、断行
- 下一篇: python自动投递简历_用python