def calibrate_gauge()

in services/read-gauge.py [0:0]


def calibrate_gauge(img,img_path, image_key,file_type):
    try:
        '''
            This function should be run using a test image in order to calibrate the range available to the dial as well as the
            units.  It works by first finding the center point and radius of the gauge.  Then it draws lines at hard coded intervals
            (separation) in degrees.  It then prompts the user to enter position in degrees of the lowest possible value of the gauge,
            as well as the starting value (which is probably zero in most cases but it won't assume that).  It will then ask for the
            position in degrees of the largest possible value of the gauge. Finally, it will ask for the units.  This assumes that
            the gauge is linear (as most probably are).
            It will return the min value with angle in degrees (as a tuple), the max value with angle in degrees (as a tuple),
            and the units (as a string).
        '''
        print('%s%s.%s' % (img_path, image_key,file_type));
        # img = cv2.imread('%s%s.%s' % (img_path, image_key,file_type))
        height, width = img.shape[:2]
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  #convert to gray
        #gray = cv2.GaussianBlur(gray, (5, 5), 0)
        # gray = cv2.medianBlur(gray, 5)

        #for testing, output gray image
        cv2.imwrite('%s%s-bw.%s' % (img_path, image_key,file_type),gray)


        #detect circles
        #restricting the search from 35-48% of the possible radii gives fairly good results across different samples.  Remember that
        #these are pixel values which correspond to the possible radii search range.
        # circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, np.array([]), 100, 50, int(height*0.35), int(height*0.48))
        circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, np.array([]), 100, 50, int(height*0.35), int(height*0.48))
        # average found circles, found it to be more accurate than trying to tune HoughCircles parameters to get just the right one
        # print(circles)
        print(circles.shape)
        a, b, c = circles.shape
        x,y,r = avg_circles(circles, b)

        #draw center and circle
        cv2.circle(img, (x, y), r, (0, 0, 255), 3, cv2.LINE_AA)  # draw circle
        cv2.circle(img, (x, y), 2, (0, 255, 0), 3, cv2.LINE_AA)  # draw center of circle

        #for testing, output circles on image
        cv2.imwrite('%s%s-circles.%s' % (img_path, image_key,file_type), img)


        #for calibration, plot lines from center going out at every 10 degrees and add marker
        #for i from 0 to 36 (every 10 deg)

        '''
        goes through the motion of a circle and sets x and y values based on the set separation spacing.  Also adds text to each
        line.  These lines and text labels serve as the reference point for the user to enter
        NOTE: by default this approach sets 0/360 to be the +x axis (if the image has a cartesian grid in the middle), the addition
        (i+9) in the text offset rotates the labels by 90 degrees so 0/360 is at the bottom (-y in cartesian).  So this assumes the
        gauge is aligned in the image, but it can be adjusted by changing the value of 9 to something else.
        '''
        separation = 10.0 #in degrees
        interval = int(360 / separation)
        p1 = np.zeros((interval,2))  #set empty arrays
        p2 = np.zeros((interval,2))
        p_text = np.zeros((interval,2))
        for i in range(0,interval):
            for j in range(0,2):
                if (j%2==0):
                    p1[i][j] = x + 0.9 * r * np.cos(separation * i * 3.14 / 180) #point for lines
                else:
                    p1[i][j] = y + 0.9 * r * np.sin(separation * i * 3.14 / 180)
        text_offset_x = 10
        text_offset_y = 5
        for i in range(0, interval):
            for j in range(0, 2):
                if (j % 2 == 0):
                    p2[i][j] = x + r * np.cos(separation * i * 3.14 / 180)
                    p_text[i][j] = x - text_offset_x + 1.2 * r * np.cos((separation) * (i+9) * 3.14 / 180) #point for text labels, i+9 rotates the labels by 90 degrees
                else:
                    p2[i][j] = y + r * np.sin(separation * i * 3.14 / 180)
                    p_text[i][j] = y + text_offset_y + 1.2* r * np.sin((separation) * (i+9) * 3.14 / 180)  # point for text labels, i+9 rotates the labels by 90 degrees

        #add the lines and labels to the image
        for i in range(0,interval):
            cv2.line(img, (int(p1[i][0]), int(p1[i][1])), (int(p2[i][0]), int(p2[i][1])),(0, 255, 0), 2)
            cv2.putText(img, '%s' %(int(i*separation)), (int(p_text[i][0]), int(p_text[i][1])), cv2.FONT_HERSHEY_SIMPLEX, 0.3,(0,0,0),1,cv2.LINE_AA)

        cv2.imwrite('%s%s-calibration.%s' % (img_path, image_key,file_type), img)

        #get user input on min, max, values, and units
        # print '%s%s-calibration.%s' % (img_path, image_key,file_type)
        # min_angle = raw_input('Min angle (lowest possible angle of dial) - in degrees: ') #the lowest possible angle
        # max_angle = raw_input('Max angle (highest possible angle) - in degrees: ') #highest possible angle
        # min_value = raw_input('Min value: ') #usually zero
        # max_value = raw_input('Max value: ') #maximum reading of the gauge
        # units = raw_input('Enter units: ')

        #for testing purposes: hardcode and comment out raw_inputs above
        # min_angle = 45
        # max_angle = 320
        # min_value = 0
        # max_value = 200
        # units = "PSI"

        return x, y, r
    except Exception as e: 
        return 0,0,0