OpenCV finds color in a circle and Python position value

What I'm trying to do is process the attendance sheet below to tell me who is there and who is not Attendance sheet

I am currently using matchTemplate, using a special black dot that finds all the filled dots (the image is first converted to grayscale). Image below

Dots matched

Then I process the matchPattern array and get about the center of each in the y direction, and I see where there are spaces corresponding to the missing students.

The problem I am facing is that this sorting works for perfect input, but my goal is to take a snapshot of a physical sheet of paper and process this? Note: the attendance sheet is made by me, so it can be changed / changed, but necessary.

I have attached a sample image, which will be shown below. test match Using my current method is just a disaster (see below). Now I'm not sure where to go from here, I tried to change the threshold, but the past .65 he can not find any images. fail

import cv2 import numpy as np from matplotlib import pyplot as plt values = [] img_rgb = cv2.imread('/home/user/Downloads/input.png') img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) template = cv2.imread('/home/user/Downloads/input_2.png',0) w, h = template.shape[::-1] res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) threshold = 0.6 loc = np.where( res >= threshold) for pt in zip(*loc[::-1]): cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2) values.append(pt[1]+h/2) cv2.imwrite('output.png',img_rgb) values.sort() pivot = values[0] count = 1 total = values[0] cleaned = [] for x in range(1,len(values)): if(values[x] < pivot+20): pivot = values[x] count = count + 1 total = total + values[x] else: print values[x] cleaned.append(int(total/count)) pivot = values[x] count = 1 total = values[x] if x == len(values)-1: cleaned.append(int(total/count)) print values print cleaned 

Here is another test image: enter image description here

+6
source share
2 answers

Typically, when analyzing paper forms, special labels on the fields and corners of the form are used to determine the scale and orientation of significant parts. For example, you can print several small squares at the borders of the form, find them with the same cv2.matchTemplate and thereby determine the area of ​​interest.

Most likely, your forms will not be completely captured (for example, they can be scaled, rotated or seen in perspective), so you also need to normalize the input. You can use perspectives or affine transformations .

You can also enhance the image using histogram alignment , noise reduction and other methods.

At this point, you should have a fully normalized image that is much closer to the "ideal input." You can try your algorithm at this input, but there is an easier way (AFAIK, something like this is used in real applications to automatically analyze the form).

Your form has a fixed layout, and you already know its angles. So why not calculate the position of each interesting fragment of the form? For instance. in the picture below I placed 4 black landmarks in the corners of the form. In a normalized image, the position of the dotted area will always be the same relative to these landmarks .

enter image description here

Finding out whether a student was in the lecture or not is as simple as splitting the dotted area into fixed square areas (one for each student), summing the pixel values ​​in that area and comparing this value with a predetermined threshold. Regions with lower values ​​are usually blacker than white (the student attended the lecture), and regions with higher values ​​are most likely white (the student was absent).

So to summarize:

  • Use landmarks to define paper corners.
  • Normalize the image with respect to these landmarks.
  • Enhance the image if necessary.
  • Calculate the position of the regions of interest.
  • Determine if a region is more likely to be black from white.
+3
source

Here is an example of how to identify points with a fairly simplified approach:

 from skimage import io, color, filter, morphology, feature, img_as_float from skimage.morphology import disk image = io.imread('dots.jpg') # Remove blue channel bw = image.copy() bw[..., 2] = 0 bw = 1 - img_as_float(color.rgb2gray(image)) big_mask = 150 small_mask = 10 min_dist = 50 bw = filter.rank.threshold_percentile(bw, disk(big_mask), p0=0.95) bw = morphology.erosion(bw, disk(small_mask)) peaks = feature.corner_peaks(bw, min_distance=min_dist, indices=True) import matplotlib.pyplot as plt f, (ax0, ax1) = plt.subplots(1, 2) ax0.imshow(image, cmap=plt.cm.gray) ax1.imshow(bw, cmap=plt.cm.gray) ax0.scatter(peaks[:, 1], peaks[:, 0], c='red', s=30) plt.show() 

Detected dots

+2
source

Source: https://habr.com/ru/post/953568/


All Articles