# Path: imgProcessor/transform/linearBlend.py
# def linearBlend(img1, img2, overlap, backgroundColor=None):
#     '''
#     Stitch 2 images vertically together.
#     Smooth the overlap area of both images with a linear fade from img1 to img2
# 
#     @param img1: numpy.2dArray
#     @param img2: numpy.2dArray of the same shape[1,2] as img1
#     @param overlap: number of pixels both images overlap
#     @returns: stitched-image
#     '''
#     (sizex, sizey) = img1.shape[:2]
# 
#     overlapping = True
#     if overlap < 0:
#         overlapping = False
#         overlap = -overlap
# 
#     # linear transparency change:
#     alpha = np.tile(np.expand_dims(np.linspace(1, 0, overlap), 1), sizey)
#     if len(img2.shape) == 3:  # multi channel img like rgb
#         # make alpha 3d with n channels
#         alpha = np.dstack(([alpha for _ in range(img2.shape[2])]))
#     if overlapping:
#         img1_cut = img1[sizex - overlap:sizex, :]
#         img2_cut = img2[0:overlap, :]
#     else:
#         # take average of last 5 rows:
#         img1_cut = np.tile(img1[-min(sizex, 5):, :].mean(
#             axis=0), (overlap, 1)).reshape(alpha.shape)
#         img2_cut = np.tile(img2[:min(img2.shape[0], 5), :].mean(
#             axis=0), (overlap, 1)).reshape(alpha.shape)
# 
#     # fill intermediate area as mixture of both images
#     #################bg transparent############
#     inter = (img1_cut * alpha + img2_cut * (1 - alpha)).astype(img1.dtype)
#     # set background areas to value of respective other img:
#     if backgroundColor is not None:
#         mask = np.logical_and(img1_cut == backgroundColor,
#                               img2_cut != backgroundColor)
#         inter[mask] = img2_cut[mask]
#         mask = np.logical_and(img2_cut == backgroundColor,
#                               img1_cut != backgroundColor)
# 
#         inter[mask] = img1_cut[mask]
#     if not overlapping:
#         overlap = 0
#     return np.vstack((img1[0:sizex - overlap, :],
#                       inter,
#                       img2[overlap:, :]))
# 
# Path: imgProcessor/imgIO.py
# def imread(img, color=None, dtype=None):
#     '''
#     dtype = 'noUint', uint8, float, 'float', ...
#     '''
#     COLOR2CV = {'gray': cv2.IMREAD_GRAYSCALE,
#                 'all': cv2.IMREAD_COLOR,
#                 None: cv2.IMREAD_ANYCOLOR
#                 }
#     c = COLOR2CV[color]
#     if callable(img):
#         img = img()
#     elif isinstance(img, string_types):
#         #         from_file = True
#         #         try:
#         #             ftype = img[img.find('.'):]
#         #             img = READERS[ftype](img)[0]
#         #         except KeyError:
#         # open with openCV
#         # grey - 8 bit
#         if dtype in (None, "noUint") or np.dtype(dtype) != np.uint8:
#             c |= cv2.IMREAD_ANYDEPTH
#         img2 = cv2.imread(img, c)
#         if img2 is None:
#             raise IOError("image '%s' is not existing" % img)
#         img = img2
# 
#     elif color == 'gray' and img.ndim == 3:  # multi channel img like rgb
#         # cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #cannot handle float64
#         img = toGray(img)
#     # transform array to uint8 array due to openCV restriction
#     if dtype is not None:
#         if isinstance(img, np.ndarray):
#             img = _changeArrayDType(img, dtype, cutHigh=False)
# 
#     return img


import cv2
import numpy as np
    import sys
    import imgProcessor
from imgProcessor.transform.linearBlend import linearBlend
from imgProcessor.imgIO import imread
from scipy.optimize.optimize import brent
    from fancytools.os.PathStr import PathStr

from __future__ import division


# import imgProcessor as iP
# from skimage.filters.edges import roberts
# from imgProcessor.filters.fastFilter import fastFilter


class StitchImages(object):

    def __init__(self, img):
        '''
        Find the Overlap between image parts and stitch them at a given edge together.
        There is no perspective correction.
        @param img: the base image
        @param gradient: whether to use image gradient for fitting
        '''
        # TODO: does not work with nan in img. so far
        self.base_img_rgb = imread(img)

    def addImg(self, img, side='bottom', overlap=50, overlapDeviation=0,
               rotation=0, rotationDeviation=0, backgroundColor=None, params=None):
        '''
        @param side: 'left', 'right', 'top', 'bottom', default side is 'bottom'
        @param overlap: overlap guess in pixels of both images
        @param overLapDeviation uncertainty of overlap -> overlap in range(ov-deviation, ov+deviation)
        @param rotation: max. rotational error between images [DEG]
        @param rotationDeviation: same as overLapDeviation, but for rotation [DEG]
        @param backgroundColor: if not None, treat this value as transparent within the stitching area
        '''

# Path: imgProcessor/transform/linearBlend.py
# def linearBlend(img1, img2, overlap, backgroundColor=None):
#     '''
#     Stitch 2 images vertically together.
#     Smooth the overlap area of both images with a linear fade from img1 to img2
# 
#     @param img1: numpy.2dArray
#     @param img2: numpy.2dArray of the same shape[1,2] as img1
#     @param overlap: number of pixels both images overlap
#     @returns: stitched-image
#     '''
#     (sizex, sizey) = img1.shape[:2]
# 
#     overlapping = True
#     if overlap < 0:
#         overlapping = False
#         overlap = -overlap
# 
#     # linear transparency change:
#     alpha = np.tile(np.expand_dims(np.linspace(1, 0, overlap), 1), sizey)
#     if len(img2.shape) == 3:  # multi channel img like rgb
#         # make alpha 3d with n channels
#         alpha = np.dstack(([alpha for _ in range(img2.shape[2])]))
#     if overlapping:
#         img1_cut = img1[sizex - overlap:sizex, :]
#         img2_cut = img2[0:overlap, :]
#     else:
#         # take average of last 5 rows:
#         img1_cut = np.tile(img1[-min(sizex, 5):, :].mean(
#             axis=0), (overlap, 1)).reshape(alpha.shape)
#         img2_cut = np.tile(img2[:min(img2.shape[0], 5), :].mean(
#             axis=0), (overlap, 1)).reshape(alpha.shape)
# 
#     # fill intermediate area as mixture of both images
#     #################bg transparent############
#     inter = (img1_cut * alpha + img2_cut * (1 - alpha)).astype(img1.dtype)
#     # set background areas to value of respective other img:
#     if backgroundColor is not None:
#         mask = np.logical_and(img1_cut == backgroundColor,
#                               img2_cut != backgroundColor)
#         inter[mask] = img2_cut[mask]
#         mask = np.logical_and(img2_cut == backgroundColor,
#                               img1_cut != backgroundColor)
# 
#         inter[mask] = img1_cut[mask]
#     if not overlapping:
#         overlap = 0
#     return np.vstack((img1[0:sizex - overlap, :],
#                       inter,
#                       img2[overlap:, :]))
# 
# Path: imgProcessor/imgIO.py
# def imread(img, color=None, dtype=None):
#     '''
#     dtype = 'noUint', uint8, float, 'float', ...
#     '''
#     COLOR2CV = {'gray': cv2.IMREAD_GRAYSCALE,
#                 'all': cv2.IMREAD_COLOR,
#                 None: cv2.IMREAD_ANYCOLOR
#                 }
#     c = COLOR2CV[color]
#     if callable(img):
#         img = img()
#     elif isinstance(img, string_types):
#         #         from_file = True
#         #         try:
#         #             ftype = img[img.find('.'):]
#         #             img = READERS[ftype](img)[0]
#         #         except KeyError:
#         # open with openCV
#         # grey - 8 bit
#         if dtype in (None, "noUint") or np.dtype(dtype) != np.uint8:
#             c |= cv2.IMREAD_ANYDEPTH
#         img2 = cv2.imread(img, c)
#         if img2 is None:
#             raise IOError("image '%s' is not existing" % img)
#         img = img2
# 
#     elif color == 'gray' and img.ndim == 3:  # multi channel img like rgb
#         # cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #cannot handle float64
#         img = toGray(img)
#     # transform array to uint8 array due to openCV restriction
#     if dtype is not None:
#         if isinstance(img, np.ndarray):
#             img = _changeArrayDType(img, dtype, cutHigh=False)
# 
#     return img


# Path: imgProcessor/transform/StitchImages.py
import cv2
import numpy as np
    import sys
    import imgProcessor
from imgProcessor.transform.linearBlend import linearBlend
from imgProcessor.imgIO import imread
from scipy.optimize.optimize import brent
    from fancytools.os.PathStr import PathStr

from __future__ import division


# import imgProcessor as iP
# from skimage.filters.edges import roberts
# from imgProcessor.filters.fastFilter import fastFilter


class StitchImages(object):

    def __init__(self, img):
        '''
        Find the Overlap between image parts and stitch them at a given edge together.
        There is no perspective correction.
        @param img: the base image
        @param gradient: whether to use image gradient for fitting
        '''
        # TODO: does not work with nan in img. so far
        self.base_img_rgb = imread(img)

    def addImg(self, img, side='bottom', overlap=50, overlapDeviation=0,
               rotation=0, rotationDeviation=0, backgroundColor=None, params=None):
        '''
        @param side: 'left', 'right', 'top', 'bottom', default side is 'bottom'
        @param overlap: overlap guess in pixels of both images
        @param overLapDeviation uncertainty of overlap -> overlap in range(ov-deviation, ov+deviation)
        @param rotation: max. rotational error between images [DEG]
        @param rotationDeviation: same as overLapDeviation, but for rotation [DEG]
        @param backgroundColor: if not None, treat this value as transparent within the stitching area
        '''

        img_rgb = imread(img)
