def process_rgb_histogram(hist, omit=[]):
    """
    omit unwanted bins and normalize histogram by dividing out total # pixels

    :param hist: color channel histogram with 256 bins
    :param omit: pixel value bins to omit, default []
    :return: normalized histogram (np.array)
    """
    import numpy as np
    from accessory import get_iterable

    if len(hist) != 256:
        msg = 'ERROR [process_rgb_histogram] Input histogram must contain ' \
              '256 bins (1 per pixel). Actual bin number = %d. ' % len(hist)
        print(msg)
        logging.error(msg)
        sys.exit()

    hist = np.array(hist).astype('float')

    for ii in get_iterable(omit):
        hist[ii] = 0

    tot_pix = sum(hist)

    try:
        norm_hist = np.divide(hist, tot_pix)
    except RuntimeWarning:
        msg = 'Trying to normalize histogram by dividing by 0 ' \
              'Setting norm_hist to 0 in result.'
        logging.debug(msg)
        norm_hist = np.zeros(len(hist))

    return norm_hist
Esempio n. 2
0
def rgbstring2index(rgbstring):
    """
    converts RGB string into array containing corresponding channel indices

    :param rgbstring: string of letters specifying desired color channels
    :return: array of rgb channel index (np.array)
    """
    import numpy as np
    import re
    from accessory import get_iterable

    if len(re.findall('[rgb]', rgbstring.lower())) != len(rgbstring):
        msg = 'ERROR [rgbstring2index] Input string ' + \
              rgbstring + 'must contain only r, g, or b characters.'
        print(msg)
        logging.error(msg)
        sys.exit()

    idx = np.array([])
    if 'r' in rgbstring.lower():
        idx = np.append(idx, 0)

    if 'g' in rgbstring.lower():
        idx = np.append(idx, 1)

    if 'b' in rgbstring.lower():
        idx = np.append(idx, 2)

    idx = idx.astype('int')

    return get_iterable(idx)
def calc_median(img, omit=[]):
    """
    calculate median pixel value of image

    :param img: 2D array of pixel values
    :param omit: pixel values to omit from calculation
    :return: median
    """
    import numpy as np
    from accessory import get_iterable

    if np.ndim(img) > 2:
        msg = 'ERROR [calc_median] Input image must be 2D grayscale (not ' \
              'RGB).'
        logging.error(msg)
        print(msg)
        sys.exit()

    # collapse image into array
    pixels = np.ravel(np.array(img))
    pixels = pixels.astype('float')

    # omit specified pixel values from median calculation
    for omit_idx in get_iterable(omit):
        pixels[pixels == omit_idx] = np.nan

    pixels = pixels[np.isfinite(pixels)]
    median = np.median(pixels)

    return median
def calc_mode(hist, omit=[]):
    """
    calculate mode from histogram

    :param hist: histogram values for 0-255
    :param omit: pixel values to omit from calculation
    :return: mode
    """
    import numpy as np
    from accessory import get_iterable

    if np.ndim(hist) > 1:
        msg = 'ERROR [calc_mode] Input must be 1D array of histogram ' \
              'frequency values.'
        logging.error(msg)
        print(msg)
        sys.exit()
    if np.size(hist) > 256:
        msg = 'ERROR [calc_mode] Input histogram data has > 256 bins.'
        logging.error(msg)
        print(msg)
        sys.exit()

    for omit_idx in get_iterable(omit):
        hist[omit_idx] = 0

    # find the index of the histogram maximum
    mode = np.argmax(hist)

    return mode
Esempio n. 5
0
def test_get_iterable():
    from accessory import get_iterable
    import numpy as np

    vec = []
    actual = [ii for ii in get_iterable(vec)]
    expected = []

    assert np.array_equal(actual, expected)

    vec = 4
    actual = [ii for ii in get_iterable(vec)]
    expected = [vec]

    assert np.array_equal(actual, expected)

    vec = (0, 5)
    actual = [ii for ii in get_iterable(vec)]
    expected = vec

    assert np.array_equal(actual, expected)
def otsu_threshold(img, omit=[], verb=False, outfile='./otsu_img.png'):
    """
    calculate the global otsu's threshold for image

    :param img: 2D array of pixel values
    :param omit: pixel values to omit from calculation
    :param verb: verbose mode to display threshold image
    :param outfile: file to output otsu image if verbose
    :return: threshold (float)
    """
    from skimage.filters import threshold_otsu
    import numpy as np
    from accessory import get_iterable

    if np.ndim(img) > 2:
        msg = 'ERROR [otsu_threshold] Input image must be 2D grayscale (not ' \
              'RGB).'
        logging.error(msg)
        print(msg)
        sys.exit()

    otsu_img = np.array(img)
    # set omitted pixel values as 0
    for omit_idx in get_iterable(omit):
        otsu_img[img == omit_idx] = np.nan
        otsu_img[np.isnan(otsu_img)] = 0

    threshold_global_otsu = threshold_otsu(otsu_img)

    if verb:
        import matplotlib.pyplot as plt
        from accessory import create_dir
        global_otsu = otsu_img >= threshold_global_otsu
        plt.imshow(global_otsu, cmap=plt.cm.gray)

        msg = '[otsu_threshold] Saving Otsu threshold image: %s' % outfile
        logging.info(msg)
        print(msg)

        create_dir(outfile)
        plt.savefig(outfile)
        plt.clf()

    return threshold_global_otsu