Programming practice (4) - python identifies coordinate points in images and saves coordinate data

Programming practice (4) - python identifies coordinate points in images and saves coordinate data

Overview

Recently, due to the needs of the US competition, it is necessary to extract accurate data from some track route maps and terrain maps, so I have learned something about this aspect. During the research process, I found that many related posts on the Internet were not very reliable. They either reported errors or did not clearly explain the functions of some functions, so I planned to write a more detailed article.

This article mainly describes the detailed process and ideas of using opencv with python interface to complete image recognition, information extraction, redrawing, and saving as excel data. It is suitable for those who are new to opencv (requires a certain foundation of numpy and matplotlib). If there are any omissions, please point them out ~

Code ideas

I will follow the ideas of my code and explain the ideas of each step and some explanations of the functions one by one;

The general idea is as follows:

  • First: image preprocessing to polarize the image;
  • Second: Extract image data
  • Step 3: Data sorting and saving

Library installation

A total of three libraries are used here

import cv2
import numpy as np
import matplotlib.pyplot as plt

The installation of numpy and matplotlib is relatively conventional, but the installation of cv2 is not the conventional pip install cv2, but opencv-python. The domestic image download address is:

pip3 install -i https://mirrors.aliyun.com/pypi/simple/ opencv-python

Image preprocessing

img = cv2.imread('你的图片路径')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

First open the image, and then process the image as an HSV grayscale image. Because our regular image pixels are in RBG space mode, we need to convert it to HSV color space mode first (if you have not seen this image format, you can search it on Baidu ) for subsequent image binarization processing;

Insert image description here

The above is the image I used. This is the route map for the Tokyo Olympics road cycling competition. What we have to do is extract the route pixels and coordinate them;

Image thinning

If the lines of the image to be processed are very thick, it will affect the subsequent recognition process, and the image needs to be refined first; if the lines of the original image are very thin (such as mine), then you can skip this step.

I directly refer to the code of a blog for image thinning. Here is a reference: Image thinning, skeleton extraction

It's very well written, you can refer to it.

Image polarization

Here I used the inRange function in the cv library. The function of this function is to perform binary processing on the read image file (that is, the first parameter of the function).

In general, we need to specify two thresholds, lowerb and upperb. Image pixels greater than upperb and less than lowerb will be converted to 0 (i.e. black ), and points within this range will be converted to 255 ( white );

low_hsv = np.array([0, 0, 221])
high_hsv = np.array([180, 30, 255])
mask = cv2.inRange(hsv, lowerb=low_hsv, upperb=high_hsv)

Let’s talk about these two thresholds in detail. If you understand the hsv color space, you can easily find that the first two lines of the code are the two values ​​​​of the hsv color space. The parameters in the numpy.array function are exactly the hue, saturation and The brightness value, because of the needs of the inRange function, we need to convert it into an array in numpy format. I need to extract all black coordinates here, so I set the black and white thresholds. You can adjust the color thresholds according to your needs.

Threshold reference: HSV basic color component range

The mask here is the image we need to extract data~

Extract data

In order to help everyone understand, let's first print and look at the specific situation of mask:

print(len(mask))
print(len(mask[0]))
for i in range(len(mask)):
    print(mask[i])

Output:

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]

You can see that the image is 1024*654, and the pixels in each row are a numpy array (the elements are not separated by commas when printed by the numpy array). The previous 24-bit hsv image has become 8-bit. Grayscale image ( each item has only one data, rather than an array of three numbers );

What we have to do is to know the horizontal and vertical coordinates of each black pixel, that is, in the pixel matrix mask, get the row number and column number with a value of 0 .

The method is also very simple. Just traverse each pixel directly, find the pixel with a value of 0, and access the column number and row number;

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)

It should be noted here that a lot of image storage data is stored from bottom to top, so when we get the column number, we need to subtract the column number of the mask from the height of the image to get the real column number.

Display and save results

matplotlib redraw

Check the image data we obtained. Note that you need to use the scatter plot mode to draw, otherwise there will be undesirable consequences. . .

plt.plot(list_x, list_y, 'o', color='r')
plt.show()

The result is as follows:

Insert image description here

It can be found that the extraction effect is still good~~

Write to excel

The explanation of this part is placed directly in the comments.

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')

You can see that the data has been saved in excel

There is actually a small problem with this extraction, that is, there are still multiple points corresponding to the same abscissa. If we need to do operations such as function analysis, we can directly use excel to group by value and then go to each group. A specific value can be used, either the maximum value or the average value, depending on personal needs.

All source code

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')

Guess you like

Origin blog.csdn.net/qq_45882682/article/details/123115247