编程实战(4)——python识别图像中的坐标点并保存坐标数据
編程實戰(4)——python識別圖像中的坐標點并保存坐標數據
文章目錄
- 編程實戰(4)——python識別圖像中的坐標點并保存坐標數據
- 綜述
- 代碼思路
- 庫的安裝
- 圖片預處理
- 圖像細化
- 圖像二極化
- 提取數據
- 結果展示和保存
- matplotlib重繪
- 寫入excel
- 全部源碼
綜述
最近因為美賽的需求,需要在提取一些賽道的路線圖和地形圖中的準確數據,因此對這方面做了一些了解。在研究的過程中,我發現網上的很多相關的帖子并不是很靠譜,不是報錯就是沒有說清楚一些函數的功能,所以我打算寫一篇比較詳細的文章。
本文主要講述利用python接口的opencv來完成圖像識別和信息提取并重新繪制、保存為excel數據的詳細過程與思路,適合opencv方面的小白觀看(需要一定的numpy和matplotlib基礎)。如有一些疏漏,請大佬們指出~
代碼思路
我會跟著我代碼的思路逐一講解每一步的思路和函數的一些解釋;
總體思路如下:
- 第一:圖片預處理,讓圖像二極化;
- 第二:提取圖片數據
- 第三步:數據整理與保存
庫的安裝
這里一共用了三個庫
import cv2 import numpy as np import matplotlib.pyplot as pltnumpy和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 xlwtwb = 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 += 1j = 1 for y in list_y:ws.write(j, 1, y)j += 1wb.save('1111.xls')可以看到數據已經保存進excel里面了
這一次提取其實還有一個小問題,就是相同的橫坐標下還是有多個對應該橫坐標的點,如果需要做函數分析之類的操作,我們可以直接用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')總結
以上是生活随笔為你收集整理的编程实战(4)——python识别图像中的坐标点并保存坐标数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样删除Word文档的强制性回车、断行
- 下一篇: python自动投递简历_用python