<gh_stars>1-10
import cv2
import numpy as np
import matplotlib.pyplot as plt

# Automatic brightness and contrast optimization with optional histogram clipping
def automatic_brightness_and_contrast(image, clip_hist_percent=1):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Calculate grayscale histogram
    hist = cv2.calcHist([gray],[0],None,[256],[0,256])
    hist_size = len(hist)

    # Calculate cumulative distribution from the histogram
    accumulator = []
    accumulator.append(float(hist[0]))
    for index in range(1, hist_size):
        accumulator.append(accumulator[index -1] + float(hist[index]))

    # Locate points to clip
    maximum = accumulator[-1]
    clip_hist_percent *= (maximum/100.0)
    clip_hist_percent /= 2.0

    # Locate left cut
    minimum_gray = 0
    while accumulator[minimum_gray] < clip_hist_percent:
        minimum_gray += 1

    # Locate right cut
    maximum_gray = hist_size -1
    while accumulator[maximum_gray] >= (maximum - clip_hist_percent):
        maximum_gray -= 1

    # Calculate alpha and beta values
    alpha = 255 / (maximum_gray - minimum_gray)
    beta = -minimum_gray * alpha

    '''
    # Calculate new histogram with desired range and show histogram 
    new_hist = cv2.calcHist([gray],[0],None,[256],[minimum_gray,maximum_gray])
    plt.plot(hist)
    plt.plot(new_hist)
    plt.xlim([0,256])
    plt.show()
    '''

    auto_result = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
    return (auto_result, alpha, beta)

def image_blurring(image):
    return cv2.bilateralFilter(image, d=9, sigmaColor=75, sigmaSpace=75)

def image_thresholding(image):
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    threshold, thresholded_image = cv2.threshold(image, thresh=0, maxval=255, type=cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    return (thresholded_image, threshold)

def edge_detection(image):
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    gx = cv2.Sobel(image, cv2.CV_32F, 1, 0, ksize=3)
    gy = cv2.Sobel(image, cv2.CV_32F, 0, 1, ksize=3)

    m = np.sqrt(gx ** 2 + gy ** 2)
    m_max = np.sqrt((0 * 255 + 1 * 255 + 2 * 255) ** 2 + (2 * 255 + 1 * 255 + 0 * 255) ** 2)
    m = m / m_max
    m = m * 255

    theta = np.arctan2(gy, gx)
    theta = theta + np.pi
    theta = (theta * 180) / np.pi
    theta = theta / 2

    hsv = np.ndarray(shape=(image.shape[0], image.shape[1], 3), dtype=np.uint8)
    hsv[:, :, 0] = theta
    hsv[:, :, 1] = np.full(shape=(image.shape[0], image.shape[1]), fill_value=255)
    hsv[:, :, 2] = m

    return cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)

def contour(image):
    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    ret, thresh = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

    closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, np.ones((5,5),np.uint8))

    contours, hierarchy = cv2.findContours(closing, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(image, contours, -1, (255, 0, 0), 3, cv2.LINE_AA)

    return image
