morgan101101
morgan101101

Reputation: 21

How can i scale a thickness of a character in image using python OpenCV?

I created one task, where I have white background and black digits.

I need to take the largest by thickness digit. I have made my picture bw, recognized all symbols, but I don't understand, how to scale thickness. I have tried arcLength(contours), but it gave me the largest by size. I have tried morphological operations, but as I undestood, it helps to remove noises and another mistakes in picture, right? And I had a thought to check the distance between neighbour points of contours, but then I thought that it would be hard because of not exact and clear form of symbols(I draw tnem on paint). So, that's all Ideas, that I had. Can you help me in this question by telling names of themes in Comp. vision and OpenCV, that could help me to solve this task? I don't need exact algorithm of solution, only themes. And if that's not OpenCV task, so which is? What library? Should I learn some pack of themes and basics before the solution of my task?

Upvotes: 2

Views: 3186

Answers (2)

kavko
kavko

Reputation: 2841

Have you thought about drawing a line from a certain point of the contour and look for points where the line intersects your contour? I mean if you get the coordinates from two points you can measure the distance. I have made a sample to demonstrate what I mean. Note that this script is meant just for the demonstration of solution and it will not work with other pictures except my sample one. I would give a better one but I have only encountered with programming a few months back.

enter image description here

So the first thing is to extract the contours which you said you have already done (mind that cv2.findContours finds white values). then you can get referential coordinates with cv2.boundingRect() - it returns x,y coordinate, width and height of an bounding rectangle for your contour (you can of course do something similar by extracting a little fracture of your contour on a mask and work from there). In my example I defined the center of the box and moved the line slightly downwards then made a line to the left (I have done it by appending to lists and converting it to arrays and there are probably a million better solutions). Then you look for points that are in your contour and in your line (those points are the points of intersection). I have calculated simply by difference of two x coordinates because it works for this demonstration but better approach would be sqrt(x2-x1)^2+(y2-y1)^2. Maybe it will give you an idea. Cheers!

Sample code:

import cv2
import numpy as np
import numpy

img = cv2.imread('Thickness2.png')
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,10,255,cv2.THRESH_BINARY_INV)
im2, cnts, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
font = cv2.FONT_HERSHEY_TRIPLEX

for c in cnts:
    two_points = []
    coord_x = []
    coord_y = []
    area = cv2.contourArea(c)
    perimeter = cv2.arcLength(c, False)
    if area > 1 and perimeter > 1:
        x,y,w,h = cv2.boundingRect(c)
        cx = int((x+(w/2))) -5
        cy = int((y+(h/2))) +15
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
        for a in range(cx, cx+70):
            coord_x.append(a)
            coord_y.append(cy)
        coord = list(zip(coord_x, coord_y))
        arrayxy = np.array(coord)
        arraycnt = np.array(c)
        for a in arraycnt:
            for b in arrayxy:
                if a[:,0] == b[0] and a[:,1] == b[1]:
                    cv2.circle(img,(b[0],b[1]), 2, (0,255,255), -1)
                    two_points.append(b)
        pointsarray = np.array(two_points)
        thickness = int(pointsarray[1,0]) - int(pointsarray[0,0])
        print(thickness)              
        cv2.line(img, (cx, cy), (cx+50, cy), (0,0,255), 1)
        cv2.putText(img, 'Thickness : '+str(thickness),(x-20, y-10), font, 0.4,(0,0,0),1,cv2.LINE_AA)

cv2.imshow('img', img)

Output:

enter image description here

Upvotes: 1

Hirabayashi Taro
Hirabayashi Taro

Reputation: 943

One possible solution that I can think of is to alternate erosion and find contours till you have only one contour left (that should be the thicker). This could work if the difference in thickness is enough, but I can also foresee many particular cases that can prevent a correct identification, so it depends very much on how is your original image.

Upvotes: 1

Related Questions