PS02- Hough circles

def hough_circles_acc(img_edges, radius=10, method='point plus', grad_x=None, grad_y=None, shouldNormalize=True):
    edgeValueIndices = np.where(img_edges == 255)
    isSinglePoint = False
    if method == 'single point' and grad_y is None and grad_x is None:
        isSinglePoint = True
        theta = getThetas(360)
        H = np.zeros((len(img_edges), len(theta[0])))
    else:
        grad_x = grad_x[edgeValueIndices].reshape(1, len(edgeValueIndices[1]))
        grad_y = grad_y[edgeValueIndices].reshape(1, len(edgeValueIndices[0]))
        theta = np.arctan2(grad_y, grad_x)
        H = np.zeros((len(img_edges), len(img_edges[0])))
    H = circles_accumulate(H, isSinglePoint, edgeValueIndices, theta, radius)
    return toUint8(H) if shouldNormalize else H

def circles_accumulate(H, isSinglePoint, edgeValues, theta, radius):
    if isSinglePoint:
        a = np.ceil(edgeValues[1].reshape(len(edgeValues[1]),1) - (radius * np.cos(theta))).astype(np.int32)
        b = np.ceil(edgeValues[0].reshape(len(edgeValues[0]),1) + (radius * np.sin(theta))).astype(np.int32)
        H = circles_accumulate_add(H, a, b)
    else:
        for i in [1, -1]:
            a = np.around(edgeValues[1].reshape(len(edgeValues[1]),1) + i * radius * np.cos(theta)).astype(np.int32)
            b = np.around(edgeValues[0].reshape(len(edgeValues[0]),1) + i * radius * np.sin(theta)).astype(np.int32)
            H = circles_accumulate_add(H, a, b)
    return H

def circles_accumulate_add(H, a, b):
    a = a.reshape(1, len(a) * len(a[0]))
    b = b.reshape(1, len(b) * len(b[0]))
    res = np.r_[b, a].transpose()
    res = res[np.logical_and(res[:,0] >= 0, res[:,0] < len(H)) & np.logical_and(res[:,1] >= 0, res[:,1] < len(H[0]))]
    np.add.at(H, res.transpose().tolist(), 1)
    return H