0

I'm trying to calculate the bending radius of a product under cyclic bending using image processing with OpenCV and Python. The image processing part is defined (the code is at Red dot coordinates detection )

The code returns center coordinates of contours of specific size. I'm now trying to populate a 2D array of these coordinates so that I can use coordinates of two adjacent points to calculate the bending radius.

The problem is that the array population should be inside the for loop and that when I allocate the array beforehand, I don't know the size.

EDIT: bellow is the code from the link above with the FOR loop for filtering out the contours by area and displaying the center coordinates.

import cv2
import numpy as np
from matplotlib import pyplot as plt
import imutils

#load image
img = cv2.imread('dot4_red.jpg')

#apply median blur, 15 means it's smoothing image 15x15 pixels

blur = cv2.medianBlur(img,15)

#convert to hsv
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)

#color definition
red_lower = np.array([0,0,240])
red_upper = np.array([10,10,255])

#red color mask (sort of thresholding, actually segmentation)
mask = cv2.inRange(hsv, red_lower, red_upper)

#copy image for, .findContours distorts the source image
mask_copy = mask.copy()

#find contours
cnts = cv2.findContours(mask_copy,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

#extract contours from the list??
cnts = imutils.grab_contours(cnts)

#count number of conoturs of specific size
s1 = 500
s2 = 10000
array = [] #create empty array of no size

for cnt in cnts:
    area = cv2.contourArea(cnt)
    moment = cv2.moments(cnt)
    if s1<area<s2:
        print area
        c_x = int(moment["m10"]/moment["m00"])
        c_y = int(moment["m01"]/moment["m00"])
        print (c_x, c_y)

        array.append(c_x, c_y)
user2882635
  • 133
  • 2
  • 19
  • 1
    We need to know what tools you are using. Some more detailed information would help us help you – David Wright May 14 '20 at 06:58
  • What language are you using? If it's Python as in the linked question, [investigate `append()`](https://stackoverflow.com/q/252703/1270789). – Ken Y-N May 14 '20 at 07:01
  • Sorry, I completely forgot to add the info on the language. I edited the original post with the code I have so far. I'm trying to add the array in the for loop used for filtering contours by area. – user2882635 May 14 '20 at 10:10

2 Answers2

1

Instead of a for-loop you could use a while-loop with arbitrary termination criteria that you could calculate during the execution of your loop. And you could dynamically append to your array using np.append(), although it is not exactly efficient. I suggest you estimate the size of your array beforehand and only append if necessary.

David Wright
  • 464
  • 6
  • 18
  • but a while loop stops when it encounters a false result. I also noticed that the np.append() only "adds" one argument while I need to fill two coordinates at each step – user2882635 May 14 '20 at 10:37
  • Yes, but you could also implement it using `while(True):` and then `break` dynamically. You are completely free to append whatever objects you like. If you need one or two coordinates does not matter at all. – David Wright May 14 '20 at 13:26
  • I checked the concept of while True, but I can't wrap my head around on how to implement that into my results of findContours which are in the form of a list (an array of point coordinates for every contour). I need to loop through these arrays, calculate the area and check if that area is within limits. I think I need to declare some variable (like i) to use it to loop through all the array. Am I missing something here? – user2882635 May 15 '20 at 06:00
  • I am not sure if I completely understand your requirements, but would it be possible to do something like this: `i = 0; while(True): ... do processing on index i...; i += 1; if(doneProcessing): break`? – David Wright May 15 '20 at 07:25
  • I found a solution, please see the answered question – user2882635 May 18 '20 at 15:05
0

Ok, I managed to figure out how to extract the center coordinates. The code is bellow. The problem is that I did not understand how to define what I wanted in Python.

The solution is simple, I created two empty lists before the FOR loop and when the IF sentence filters out the contour of specific area, the x and y coordinates get written in separate lists. Then I can call specific coordinates for further calculation.

Thanks for all the pointers and ideas.

import cv2
import numpy as np
import scipy
from matplotlib import pyplot as plt
import imutils

#load image
img = cv2.imread('dot4_red.jpg')

#apply median blur, 15 means it's smoothing image 15x15 pixels
blur = cv2.medianBlur(img,15)

#convert to hsv
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)

#color definition
red_lower = np.array([160,210,230])
red_upper = np.array([180,255,255])

#red color mask (sort of thresholding, actually segmentation)
mask = cv2.inRange(hsv, red_lower, red_upper)

#copy image for, .findContours distorts the source image
mask_copy = mask.copy()

#find contours
cnts = cv2.findContours(mask_copy,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

#extract contours from the list??
cnts = imutils.grab_contours(cnts)

#contour size filter
s1 = 500
s2 = 10000

#calculate center coord and display data
x = []
y = []

for cnt in cnts:
    area = cv2.contourArea(cnt)
    moment = cv2.moments(cnt)
    if s1<area<s2:
        print area
        c_x = int(moment["m10"]/moment["m00"])
        c_y = int(moment["m01"]/moment["m00"])
        x.append(c_x)
        y.append(c_y)
        print (c_x, c_y)

print x
print y
user2882635
  • 133
  • 2
  • 19