Ask Your Question
0

Drawing Gradient Directions

asked 2018-07-20 03:19:10 -0600

sazr gravatar image

I have created some code to visually display the average gradient direction in a cell/kernel. My questions are:

  • Is my method of calculating the average gradient direction correct? I am aware of a different method (see *) but unsure which is better/more accurate.
  • Is my normalisation of a degrees value to a hue value correct? Ie, normalising a value that can be 0-359 to a value between 0-179 by simply dividing by 2?
  • Most importantly am I accurately calculating and representing the average gradient direction over a series of cells?

*Alt method to calculate the average gradient direction:

hMean = cv2.mean(sobelX)
vMean = cv2.mean(sobelY)
avg_dir = math.atan2(-vMean[0], hMean[0])

Draw gradient directions:

import cv2
import math
import numpy as np

np.set_printoptions(precision=3, threshold=np.inf, linewidth=np.inf, suppress=True)

def get_roi(src, pt1, pt2):

    col1, col2 = (pt1[0], pt2[0]) if pt1[0] < pt2[0] else (pt2[0], pt1[0])
    row1, row2 = (pt1[1], pt2[1]) if pt1[1] < pt2[1] else (pt2[1], pt1[1])
    return src[row1:row2, col1:col2]

def get_gradient_direction_line(avg_dir, cellUpperLeft, cellW, cellH, scale=0.8):

    halfScale = scale/2;
    centrePt = (int(cellUpperLeft[0] + (cellW/2)), int(cellUpperLeft[1] + (cellH/2)))
    strtPt = (int(centrePt[0] - (cellW * halfScale * math.cos(avg_dir))), int(centrePt[1] - (cellH * halfScale * math.sin(avg_dir))))
    endPt = (int(centrePt[0] + (cellW * halfScale * math.cos(avg_dir))), int(centrePt[1] + (cellH * halfScale * math.sin(avg_dir))))
    return [strtPt, endPt]

def get_gradient_directions_arrows(direction, kernel_w=3, kernel_h=3):

    arrows = np.zeros(direction.shape, dtype=np.uint8)
    n_cols = int(direction.shape[1] / kernel_w)
    n_rows = int(direction.shape[0] / kernel_h)

    for c in range(n_cols):
        # Draw grid lines
        cv2.line(arrows, (c*kernel_w, 0), (c*kernel_w, direction.shape[0]), (255,255,255), 1)
        cv2.line(arrows, (0, c*kernel_h), (direction.shape[1], c*kernel_h), (255,255,255), 1)

        for r in range(n_rows):
            roiUpperleft = (c*kernel_w, r*kernel_h)
            roi = get_roi(direction, roiUpperleft, ((c+1)*kernel_w, (r+1)*kernel_h))
            avg_dir = cv2.mean(roi)[0]
            arrow_pnts = get_gradient_direction_line(avg_dir, roiUpperleft, kernel_w, kernel_h)
            cv2.arrowedLine(arrows, arrow_pnts[0], arrow_pnts[1], (255,255,255), 1)

    return arrows

def get_gradient_directions_colours(direction, kernel_w=3, kernel_h=3):
    # (red=0°; yellow=60°, green=120°, blue=240°...)

    hsv = np.zeros((direction.shape[0], direction.shape[1], 3), dtype=np.uint8)
    hsv = cv2.cvtColor(hsv, cv2.COLOR_BGR2HSV)
    n_cols = int(direction.shape[1] / kernel_w)
    n_rows = int(direction.shape[0] / kernel_h)

    for c in range(n_cols):
        # Draw grid lines
        cv2.line(hsv, (c*kernel_w, 0), (c*kernel_w, direction.shape[0]), (180,255,255), 1)
        cv2.line(hsv, (0, c*kernel_h), (direction.shape[1], c*kernel_h), (180,255,255), 1)

        for r in range(n_rows):
            roiUpperleft = (c*kernel_w, r*kernel_h)
            roi = get_roi(direction, roiUpperleft, ((c+1)*kernel_w, (r+1)*kernel_h))
            avg_dir = cv2.mean(roi)[0]
            # avg_dir will be value between 0-359. HSV hue needs a value between 0-179
            avg_dir /= 2
            arrow_pnts = get_gradient_direction_line(avg_dir, roiUpperleft, kernel_w, kernel_h)
            cv2.rectangle(hsv, roiUpperleft, ((c+1)*kernel_w, (r+1)*kernel_h), (avg_dir, 255,255), -1)

    bgr = cv2.cvtColor(hsv, cv2 ...
(more)
edit retag flag offensive close merge delete

1 answer

Sort by » oldest newest most voted
0

answered 2018-07-24 06:37:22 -0600

  • Is my method of calculating the average gradient direction correct? I am aware of a different method (see *) but unsure which is better/more accurate.

I do think that the idea is correct. However your star has no link. Might want to take a look at histogram of oriented gradients, which does exactly what you want, but which is quite a commonly used technique to do so.

  • Is my normalisation of a degrees value to a hue value correct? Ie, normalising a value that can be 0-359 to a value between 0-179 by simply dividing by 2?

There is no relation between degrees and hue values, but your encoding seems correct, however be aware that you loose precision this way.

  • Most importantly am I accurately calculating and representing the average gradient direction over a series of cells?

I do think so. However what I still do not get is why would one want to calculate gradients of the HSV image rather than the RGB image? In my understanding this transformation does not locate gradients better.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-07-20 03:19:10 -0600

Seen: 826 times

Last updated: Jul 24 '18