from qrdecode import QRDecoder,Scanner
import matplotlib.pyplot as plt
import numpy as np
import cv2
import itertools
from qrdecode.utils.patterns import *


def _farthest_cnt2box(cnt):
    # Farthest points:
    # We find the furthest point for every quadrant of the auxiliary rectangle.

    # We call a OpenCV function that creates a bounding rectangle over the contour.
    x, y, w, h = cv2.boundingRect(cnt)

    # We define a set of auxiliary points to trim the contour into 4 pieces.
    center = np.array((x + w / 2, y + h / 2))
    distances = [0, 0, 0, 0]
    point = [0, 0, 0, 0]

    for index, cnt_point in enumerate(cnt):
        cnt_point = cnt_point.tolist()[0]
        # print(point)
        d = distance(center, cnt_point)
        if cnt_point[0] < center[0] and cnt_point[1] < center[1]:
            if d > distances[0]:
                distances[0] = d
                point[0] = np.array([cnt_point])
        elif cnt_point[0] > center[0] and cnt_point[1] < center[1]:
            if d > distances[1]:
                distances[1] = d
                point[1] = np.array([cnt_point])
        elif cnt_point[0] > center[0] and cnt_point[1] > center[1]:
            if d > distances[2]:
                distances[2] = d
                point[2] = np.array([cnt_point])
        elif cnt_point[0] < center[0] and cnt_point[1] > center[1]:
            if d > distances[3]:
                distances[3] = d
                point[3] = np.array([cnt_point])

    return np.array(point)


def _poly_approximation_cnt2box(cnt):

    # We call a OpenCV function that creates a bounding rectangle over the contour.
    x, y, w, h = cv2.boundingRect(cnt)

    center = (x + w / 2, y + h / 2)  # center of the rectangle

    # By doing an polygon approximation.
    arc_length = cv2.arcLength(cnt, True)
    for ratio in np.arange(0, 1, 0.05):
        # From the OpenCV computed length of the contour we define a "density" for the approximation.
        epsilon = ratio * arc_length
        # We call the OpenCV solution for the approximation.
        approx = cv2.approxPolyDP(cnt, epsilon, True)
        if len(approx) == 4:
            break

    # The approx solution corners are ordered clockwise. However, their position in the list is random.
    # We can use again the bounding box to order them.
    point = approx[0, :, :][0]
    if point[0] < center[0] and point[1] < center[1]:
        k = 0
    elif point[0] > center[0] and point[1] < center[1]:
        k = 3
    elif point[0] > center[0] and point[1] > center[1]:
        k = 2
    elif point[0] < center[0] and point[1] > center[1]:
        k = 1

    point = np.concatenate((approx[k:], approx[0:k]))

    return point


def cnt2box(contours, method="farthest"):
    # Now, we have to found the vertices of the 3 found candidates. We have two posibilities.
    # By finding the farthest point from the center. Or doing an aproximation of the contour.

    func_mapping = {
        "farthest": _farthest_cnt2box,
        "approx": _poly_approximation_cnt2box,
        "approximation": _poly_approximation_cnt2box,
        "polygon": _poly_approximation_cnt2box,
    }

    contours_boxes = []

    for cnt in contours:
        try:
            box = func_mapping[method](cnt)
            contours_boxes.append(box)
        except Exception as e:
            raise e
            # print("Such method failed, due to: {}".format(e))

    return contours_boxes


# TODO change the idea of the filter inputs, not the "hierarchy" structure, preferable the area relations!
def position_pattern_filter(i, h, a):
    unit_area = a[2] / 9
    if unit_area:
        return not i == 0 \
               and ((h[0][0] == i + 3) or (h[0][0] == -1)) \
               and (h[0][1] <= i - 1) \
               and (h[0][2] == i + 1) \
               and (h[1][2] == i + 2) \
               and (h[1][0] == -1) \
               and (49 / 2 < a[0] / unit_area < 49 * 2) \
               and (15 / 2 < a[1] / unit_area < 25 * 2)
    else:
        return None


def alignment_pattern_filter(i, h, a):
    if a[1]:
        return not i == 0 \
               and h[1][3] == i - 1 \
               and h[1][0] == -1 and h[1][1] == -1 and h[1][2] == -1 \
               and (9 / 2 < a[0] / a[1] < 9 * 1.2)
    else:
        return None


def dot_pattern_filter(i, h, a, bit_size=1):
    s2 = bit_size ** 2
    if a[1]:
        return s2 * 0.5 < a[1] < s2 * 1.5


def filter_contours(contours, hierarchy, filter_func, ini, depth, **kwargs):
    # ini=0, depth=3, **kwargs):
    contour_moments = []
    contour_mc = []

    precandidates = []
    precandidates_mc = []
    for index, contour in enumerate(contours):
        m = cv2.moments(contour)
        contour_moments.append(m)

        # It is possible to have a division by 0 doing the calculus of the center of mass, so we can handle it.
        if m['m00']:
            centroid_x = int(m['m10'] / m['m00'])
            centroid_y = int(m['m01'] / m['m00'])
            contour_mc.append((centroid_x, centroid_y))
        else:
            contour_mc.append((None, None))

        # Now we have to evaluate the contour properties to determine if it is a possible "precandidate"
        # for being a position pattern.
        if index <= (len(contours) - depth):
            h_vector = []
            a_vector = []

            for ii in range(depth):
                h_vector.append(hierarchy[0, index + ii + ini, :])
                a_vector.append(cv2.contourArea(contours[index + ii + ini]))

            fargs = [index, h_vector, a_vector]

            if filter_func(*fargs, **kwargs):
                precandidates.append(contour)
                precandidates_mc.append(contour_mc[-1])

    return precandidates, precandidates_mc


def find_position_patterns(capture):

    img_contours = capture.img.copy()
    pre, pre_mc = filter_contours(capture.contours,
                                  capture.hirearchy,
                                  position_pattern_filter,
                                  depth=3)

    # We can group in pairs the candidates in order to compute their relative distance.
    pre_mc_pairs = list(itertools.combinations(pre_mc, 2))
    pre_mc_dista = [distance(x[0], x[1]) for x in pre_mc_pairs]

    # Then we create all the posible permutations of these distances and check one that majorizes.
    major_dist_map = list(map(lambda x: (x[0] > x[1]) and (x[0] > x[2]), itertools.permutations(pre_mc_dista)))
    index = major_dist_map.index(True)

    # We have to recreate a list in which we order the precandidates as follows:
    # The first element should be the center that not takes place in the first distance of the major_dist_map
    # To do so, we can reverse the original list, and with the help of itertools, we make it.
    pre.reverse()
    pre_mc.reverse()
    capture.position_patterns = list(list(itertools.permutations(pre))[index])
    capture.position_patterns_mc = list(list(itertools.permutations(pre_mc))[index])
    cv2.drawContours(img_contours, capture.position_patterns, -1, (0, 255, 0), 3)
    for mc in capture.position_patterns_mc:
        cv2.circle(img_contours, mc, 2, (0, 255, 0), -1)
    return img_contours, capture.position_patterns, capture.position_patterns_mc


def find_aligment_patterns(capture, hirearchy, contours, bit_size, gray, lim, of):
    # filtre Area
    candidats1 = []
    candidats3 = []
    candidats5 = []
    bolea = []
    verq = []
    var = 0
    for contour in contours:
        ca = cv2.contourArea(contour)
        if (ca >= ((bit_size * 25) - bit_size * 2) and (ca <= (bit_size * 25) + bit_size * 2)):
            mom = cv2.moments(contour)
            cx = int(mom['m10'] / mom['m00'])
            cy = int(mom['m01'] / mom['m00'])
            for l in lim:
                if cx > l[0] + of and cx < l[1] - of:
                    if cy > l[2] + of and cy < l[3] - of:
                        candidats5.append(contour)
        elif ((ca <= (bit_size * 2)) and ca >= (bit_size * 0.25)):
            mom = cv2.moments(contour)
            cx = int(mom['m10'] / mom['m00'])
            cy = int(mom['m01'] / mom['m00'])
            for l in lim:
                if cx > l[0] + of and cx < l[1] - of:
                    if cy > l[2] + of and cy < l[3] - of:
                        candidats1.append(contour)
                        var = var + 1
        elif ((ca <= (bit_size * 9) + (bit_size * 3) and (ca >= (bit_size * 9) - (bit_size * 3)))):
            mom = cv2.moments(contour)
            cx = int(mom['m10'] / mom['m00'])
            cy = int(mom['m01'] / mom['m00'])
            for l in lim:
                if cx > l[0] + of and cx < l[1] - of:
                    if cy > l[2] + of and cy < l[3] - of:
                        candidats3.append(contour)
                        var = var + 1

            '''
            #mètode mostreig trobant pixels blancs i negres  PD: no acaba de funcionar 
                pp_min = np.amin(contour, axis=0)
                pp_max = np.amax(contour, axis=0)
                mom = cv2.moments(contour)
                cx = int(mom['m10'] / mom['m00'])
                cy = int(mom['m01'] / mom['m00'])
                con = [0, 0, 0, 0, 0]
                cv2.drawContours(tigre,contour, -1, (0, 255, 0), 3)
                cv2.circle(tigre, (pp_min[0][0], cy), 1, (0, 0, 255), -1)
                cv2.circle(tigre, (cx, pp_min[0][1]), 1, (255, 0, 0), -1)


                # TODO eix x
                # analitzem els pixels del contorn i ho separem amb blocs de blancs i negres
                for c in range(pp_max[0][0] - pp_min[0][0]):
                    px = gray[(pp_min[0][0] + c), cy]
                    if px > 127 and con[0] == 0:
                        pass
                    elif px < 127 and con[1] == 0:
                        con[0] = con[0] + 1
                    elif px > 127 and con[2] == 0:
                        con[1] = con[1] + 1
                    elif px < 127 and con[3] == 0:
                        con[2] = con[2] + 1
                    elif px > 127 and con[4] == 0:
                        con[3] = con[3] + 1
                    else:
                        con[4] = con[4] + 1
                    cv2.circle(tigre, (pp_min[0][0]+c, cy), 1, (0, 0, 255), -1)
                    # OpenCV solution for performing the transform.


                # fem la mitjana dels pixels blancs i negres de mida 1
                nor = (con[0] + con[1] + con[3] + con[4]) / 4
                verx = True
                # filtrem perquè es compleixi la condició PP : 1:1:3:1:1     AP : 1:1:1:1:1
                for c in range(len(con)):
                    if con[c] >= nor - 5 and con[c] <= nor + 5:
                        verx = verx and True
                    else:
                        verx = verx and False

                # TODO eix y

                con = [0, 0, 0, 0, 0]
                nor = 0
                if (pp_max[0][0]-pp_min[0][0])>=((pp_max[0][1]-pp_min[0][1])-2) and (pp_max[0][0] - pp_min[0][0]) <= ((pp_max[0][1] - pp_min[0][1]) + 2):
                    verq.append(True)
                    candidats.append(contour)
                else:
                    verq.append(False)


                for c in range(pp_max[0][1] - pp_min[0][1]):
                    px = gray[(cx, pp_min[0][1] + c)]
                    if px > 127 and con[0] == 0:
                        pass
                    elif px < 127 and con[1] == 0:
                        con[0] = con[0] + 1
                    elif px > 127 and con[2] == 0:
                        con[1] = con[1] + 1
                    elif px < 127 and con[3] == 0:
                        con[2] = con[2] + 1
                    elif px > 127 and con[4] == 0:
                        con[3] = con[3] + 1
                    else:
                        con[4] = con[4] + 1
                    cv2.circle(tigre, (cx, pp_min[0][1] + c), 1, (0, 0, 255), -1)
                # fem la mitjana dels pixels blancs i negres de mida 1
                nor = (con[0] + con[1] + con[3] + con[4]) / 4
                very = True
                # filtrem perquè es compleixi la condició PP : 1:1:3:1:1     AP : 1:1:1:1:1
                for c in range(len(con)):
                    if con[c] >= nor - 5 and con[c] <= nor + 5:
                        very = very and True
                    else:
                        very = very and False

                bolea.append((verx, very))

                if very == True and verx == True :
                    candidats.append(contour)
                '''

    return candidats5, candidats3, candidats1


def func_mascara_tri_1():
    matrix = np.zeros([600, 600])
    des = 300
    for x in range(0, 300):
        for y in range(0, des):
            matrix[x, y] = 255
        if x > 150:
            des = des - 1

    return matrix


def func_mascara_tri_2(start_point):
    matrix = np.zeros([600, 600])
    des = 0
    for x in range(start_point[0], start_point[0] - 150, -1):
        for y in range(start_point[1] + des, 150 + start_point[1]):
            matrix[x, y] = 255
        des = des + 1

    return matrix


def func_mascara_tri_3():
    matrix = np.zeros([600, 600])
    des = 300
    for x in range(300, 600):
        for y in range(0, des):
            matrix[y, x] = 255
        des = des - 1

    return matrix


def func_mascara_tri_4():
    matrix = np.zeros([600, 600])
    des = 0
    for x in range(300, 600):
        for y in range(300, 300 - des - 1, -1):
            matrix[y, x] = 255
        des = des + 1

    return matrix


def func_mascara_tri_5():
    matrix = np.zeros([600, 600])
    des = 300
    for x in range(0, 300):
        for y in range(300, des + 300):
            matrix[y, x] = 255
        des = des - 1

    return matrix


def func_mascara_tri_6():
    matrix = np.zeros([600, 600])
    des = 0
    for x in range(0, 300):
        for y in range(599, 599 - des, -1):
            matrix[y, x] = 255
        des = des + 1

    return matrix


def func_mascara_tri_7(start_point):
    matrix = np.zeros([600, 600])
    des = 150
    for x in range(150):
        for y in range(des):
            matrix[x + start_point[0], y + start_point[1]] = 255
        des = des - 1

    return matrix


def func_mascara_tri_8():
    matrix = np.zeros([600, 600])
    des = 0
    for x in range(300, 599):
        for y in range(599, 450 - des, -1):
            matrix[x, y] = 255
        if x < 450:
            des = des + 1

    return matrix


def find_one_corner(img_gray, pp, num):
    # pp position pattern contours
    # num de corner que es vol buscar de 1 al 4 ordenats de esquerra a dreta i de dalt cap a baix
    gray = np.float32(img_gray)
    # dst = cv2.cornerHarris(gray, 2, 3, 0.04)
    dst = cv2.goodFeaturesToTrack(gray, 2000, 0.001, 5)
    dst = np.int0(dst)
    point = None
    res = 1
    while point == None:
        if num == 1:
            for d in dst:
                x, y = d.ravel()
                if (min(pp[:, 0][:, 0]) - res) <= x <= (min(pp[:, 0][:, 0]) + res):
                    if min(pp[:, 0][:, 1]) - res <= y <= min(pp[:, 0][:, 1]) + res:
                        point = (x, y)
        elif num == 2:
            for d in dst:
                x, y = d.ravel()
                if (max(pp[:, 0][:, 0]) - res) <= x <= (max(pp[:, 0][:, 0]) + res):
                    if min(pp[:, 0][:, 1]) - res <= y <= min(pp[:, 0][:, 1]) + res:
                        point = (x, y)
        elif num == 3:
            for d in dst:
                x, y = d.ravel()
                if (min(pp[:, 0][:, 0]) - res) <= x <= (min(pp[:, 0][:, 0]) + res):
                    if max(pp[:, 0][:, 1]) - res <= y <= max(pp[:, 0][:, 1]) + res:
                        point = (x, y)
        elif num == 4:
            for d in dst:
                x, y = d.ravel()
                if (max(pp[:, 0][:, 0]) - res) <= x <= (max(pp[:, 0][:, 0]) + res):
                    if max(pp[:, 0][:, 1]) - res <= y <= max(pp[:, 0][:, 1]) + res:
                        point = (x, y)
        res = res + 1

    return point


def find_corners_pp(img_gray, pp):
    corners = []

    a = find_one_corner(img_gray, pp, 1)
    s = find_one_corner(img_gray, pp, 2)
    d = find_one_corner(img_gray, pp, 3)
    f = find_one_corner(img_gray, pp, 4)

    corners = [a, s, d, f]

    return corners


def dist_points(point1, point2):
    dx = point1[0] - point2[0]
    dy = point1[0] - point2[1]
    return (dx * dx + dy * dy) ** 0.5

thres = [ 'sweep']
th = [0, 32, 64, 96, 128, 160, 192, 224, 255]
path = './test_qr_v3.jpg'

qr_size = 235
border = 10

scanner = Scanner(path, threshold=thres, th_values=th)

qr_list = scanner.scan()

qr = qr_list[0]

# qr = decoder.decode(border=border, qr_size=qr_size, shift_correction=True)

size_tuple = (border + qr_size, border + qr_size)

tigre = cv2.warpPerspective(scanner.img,
                            scanner.warp_matrix, size_tuple,
                            borderMode=cv2.BORDER_CONSTANT,
                            borderValue=(255, 255, 255))

scanner.position_patterns_mc = []
scanner.position_patterns = []

scanner.img_gray = cv2.cvtColor(tigre, cv2.COLOR_RGB2GRAY)
scanner.get_contours()

#TERROR roger
# position patterns de la imatge transformada
for thres in scanner.threshold:
    if thres=='sweep':
        for thres_val in scanner.th_values:
            find_position_patterns(scanner, scanner.hierarchy_lists[thres][thres_val], scanner.contours_lists[thres][thres_val])

    else:
        find_position_patterns(scanner, scanner.hierarchy_lists[thres],
                               scanner.contours_lists[thres])

#Calculem el bit size teòric per cada position pattern
area_pp_0 = cv2.contourArea(scanner.position_patterns[0])
bit_size_0 = area_pp_0/49

area_pp_1 = cv2.contourArea(scanner.position_patterns[1])
bit_size_1 = area_pp_1 / 49

area_pp_2 = cv2.contourArea(scanner.position_patterns[2])
bit_size_2 = area_pp_2 / 49

bit_size = (bit_size_1 + bit_size_2 + bit_size_0) / 3
bit_c = sqrt(bit_size)

'''
filtre per mostreig de alignment patterns

pp_min = np.amin(self.position_patterns[0],axis=0)
pp_max = np.amax(self.position_patterns[0],axis=0)
mom = cv2.moments(self.position_patterns[0])
cx = int(mom['m10']/mom['m00'])
cy = int(mom['m01']/mom['m00'])
con = [0,0,0,0,0]

cv2.circle(self.tigre,(pp_min[0][0],cy),1,(0,0,255), -1)
cv2.circle(self.tigre, (cx, pp_min[0][1]), 1, (255, 0, 0), -1)
cv2.imshow('qrcode', self.tigre)
cv2.waitKey(0)
cv2.destroyAllWindows()

#TODO eix x
#analitzem els pixels del contorn i ho separem amb blocs de blancs i negres
for c in range(pp_max[0][0]-pp_min[0][0]):
    px = self.img_gray[(pp_min[0][0]+c), cy]
    if px <127 and con[1]==0:
        con[0]=con[0]+1
    elif px >127 and con[2]==0:
        con[1]=con[1]+1
    elif px < 127 and con[3] == 0:
        con[2] = con[2] + 1
    elif px > 127 and con[4] == 0:
        con[3] = con[3] + 1
    else:
        con[4] = con[4]+1
# fem la mitjana dels pixels blancs i negres de mida 1
nor = (con[0]+con[1]+con[3]+con[4])/4
verx = True
#filtrem perquè es compleixi la condició PP : 1:1:3:1:1     AP : 1:1:1:1:1
for c in range(len(con)):
    if c==0 or c == 1 or c == 3 or c == 4:
        if con[c]>=nor-1 and con[c]<=nor+1:
            verx = verx and True
        else :
            verx = verx and False
    elif c==2:
        if con[c]>=(3*nor)-1 and con[c]<=(3*nor)+1:
            verx = verx and True
        else:
            verx = verx and False
#TODO eix y

con = [0,0,0,0,0]
nor = 0

print(pp_min[0][0])
print(pp_min[0][1])
for c in range(pp_max[0][1] - pp_min[0][1]):
    px = self.img_gray[(cx, pp_min[0][1] + c)]
    if px>127 and con[0]==0:
        pass
    elif px < 127 and con[1] == 0:
        con[0] = con[0] + 1
    elif px > 127 and con[2] == 0:
        con[1] = con[1] + 1
    elif px < 127 and con[3] == 0:
        con[2] = con[2] + 1
    elif px > 127 and con[4] == 0:
        con[3] = con[3] + 1
    else:
        con[4] = con[4] + 1
# fem la mitjana dels pixels blancs i negres de mida 1
nor = (con[0] + con[1] + con[3] + con[4]) / 4
very = True
# filtrem perquè es compleixi la condició PP : 1:1:3:1:1     AP : 1:1:1:1:1
for c in range(len(con)):
    if c == 0 or c == 1 or c == 3 or c == 4:
        if con[c] >= nor - 1 and con[c] <= nor + 1:
            very = very and True
        else:
            very = very and False
    elif c == 2:
        if con[c] >= (3 * nor) - 1 and con[c] <= (3 * nor) + 1:
            very = very and True
        else:
            very = very and False
            
'''

# S'ha d'acabar de fer la funció perquè es pugui executar per a qualsevol tipus de threshold i per qualsevol valor
# i determini els millors casos

thres = 'sweep'
thres_val = 192
img_size = 244
sec = int(img_size/3)
of = int(sec/3)


lim = [(sec, 2*sec, 0, sec),
       (0, sec, sec, 2*sec),
       (sec, 2*sec, sec, 2*sec),
       (2*sec, 3*sec, sec, 2*sec),
       (sec, 2*sec, 2*sec, 3*sec),
       (2*sec, 3*sec, 2*sec, 3*sec)]

#Buscador de alignment patterns a trabés de les
candi5, candi3, candi1= find_aligment_patterns(scanner, scanner.hierarchy_lists[thres][thres_val],
                        scanner.contours_lists[thres][thres_val], bit_size, scanner.img_gray, lim, of)

#Caluluador de moments dels alignment patterns per cada area
moments_des =[]
c5 = []
c3 = []
c1 = []

for c in range(len(candi5)):
    m5 = cv2.moments(candi5[c])
    m3 = cv2.moments(candi3[c])
    m1 = cv2.moments(candi1[c])
    c5.append((int(m5['m10'] / m5['m00']), int(m5['m01'] / m5['m00'])))
    c3.append((int(m3['m10'] / m3['m00']), int(m3['m01'] / m3['m00'])))
    c1.append((int(m1['m10'] / m1['m00']), int(m1['m01'] / m1['m00'])))
c5.sort()
c3.sort()
c1.sort()

for i in range(len(c5)):
    moments_des.append((np.std((c5[i][0],c3[i][0],c5[i][0])),np.std((c5[i][1], c3[i][1], c5[i][1]))))

cm_ap= []
for contour in candi5:
    m = cv2.moments(contour)
    cm_ap.append((int(m['m10'] / m['m00']),int(m['m01'] / m['m00'])))

# sordenen els alignment patterns
#     0
# 3   2   1
#     5   4
cm_ap.sort()

#mascares
mascara_1 = func_mascara_tri_1()                #correcte
mascara_2 = func_mascara_tri_2((300,150))       #correcte
mascara_3 = func_mascara_tri_3()                #correcte
mascara_4 = func_mascara_tri_4()                #correcte
mascara_5 = func_mascara_tri_5()                #correcte
mascara_6 = func_mascara_tri_6()                #correcte
mascara_7 = func_mascara_tri_7((300,300))       #correcte
mascara_8 = func_mascara_tri_8()                #correcte


triangles = 0
#triangles == 0 transºformades affine per traingles FUNCIONA
#triangles == 1 fins corners i intentar fer la nova transformada
crop_dst_1 = np.zeros((600,600,3),np.uint8)

if triangles==0:
    dst_f = []
    crop_dst_1 = np.zeros((600,600,3),np.uint8)
    crop_dst_2 = np.zeros((600,600,3), np.uint8)
    #primera transformada
    dst_1 = np.float32([[150,300],[300,150],[150,150]])
    src_1 = np.float32([cm_ap[0], cm_ap[3],find_one_corner(scanner.img_gray, scanner.position_patterns[0], 4)])
    M = cv2.getAffineTransform(src_1,dst_1)
    dst_1 = cv2.warpAffine(tigre, M, (600, 600))
    for x in range(0,300):
        for y in range(0,300):
            if mascara_1[x][y]==255:
                crop_dst_1[x,y] = [int(dst_1[x, y][0]), int(dst_1[x, y][1]), int(dst_1[x, y][2])]

    #segona trasnformada
    dst_2 =np.float32([[150, 300], [300, 300], [300, 150]])
    src_2 = np.float32([cm_ap[0], cm_ap[2], cm_ap[3]])
    M = cv2.getAffineTransform(src_2, dst_2)
    dst_2 = cv2.warpAffine(tigre, M, (600, 600))
    for x in range(150,300):
        for y in range(150,300):
            if mascara_2[x][y]==255:
                crop_dst_1[x,y] = [int(dst_2[x, y][0]), int(dst_2[x, y][1]), int(dst_2[x, y][2])]

    # tercera  trasnformada
    dst_3 = np.float32([[300, 150], [450, 150], [300, 300]])
    src_3 = np.float32([cm_ap[3], find_one_corner(scanner.img_gray, scanner.position_patterns[1], 3), cm_ap[2]])
    M = cv2.getAffineTransform(src_3, dst_3)
    dst_3 = cv2.warpAffine(tigre, M, (600, 600))
    for x in range(0, 600):
        for y in range(300, 600):
            if mascara_3[x][y] == 255:
                crop_dst_1[x, y] = [int(dst_3[x, y][0]), int(dst_3[x, y][1]), int(dst_3[x, y][2])]

    # quarta trasnformada
    dst_4 = np.float32([[450, 150], [300, 150], [300, 300]])
    src_4 = np.float32([find_one_corner(scanner.img_gray, scanner.position_patterns[1], 3), cm_ap[3], cm_ap[2]])
    M = cv2.getAffineTransform(src_4, dst_4)
    dst_4 = cv2.warpAffine(tigre, M, (600, 600))
    for x in range(0, 300):
        for y in range(300, 600):
            if mascara_4[x][y] == 255:
                crop_dst_1[x, y] = [int(dst_4[x, y][0]), int(dst_4[x, y][1]), int(dst_4[x, y][2])]

    # quinquena transformada
    dst_1 = np.float32([[150, 300], [300, 300], [150, 450]])
    src_1 = np.float32([cm_ap[0], cm_ap[2], find_one_corner(scanner.img_gray, scanner.position_patterns[2], 2)])
    M = cv2.getAffineTransform(src_1, dst_1)
    dst_1 = cv2.warpAffine(tigre, M, (600, 600))
    for x in range(300, 600):
        for y in range(0, 300):
            if mascara_5[x][y] == 255:
                crop_dst_1[x, y] = [int(dst_1[x, y][0]), int(dst_1[x, y][1]), int(dst_1[x, y][2])]

    # sisena trasnformada
    dst_2 = np.float32([[300, 300], [150, 450], [300, 450]])
    src_2 = np.float32([cm_ap[2], find_one_corner(scanner.img_gray, scanner.position_patterns[2], 2), cm_ap[1]])
    M = cv2.getAffineTransform(src_2, dst_2)
    dst_2 = cv2.warpAffine(tigre, M, (600, 600))
    for x in range(300, 600):
        for y in range(0, 300):
            if mascara_6[x][y] == 255:
                crop_dst_1[x, y] = [int(dst_2[x, y][0]), int(dst_2[x, y][1]), int(dst_2[x, y][2])]

    # setema  trasnformada
    dst_3 = np.float32([[300, 450], [450, 300], [300, 300]])
    src_3 = np.float32([cm_ap[1], cm_ap[5], cm_ap[2]])
    M = cv2.getAffineTransform(src_3, dst_3)
    dst_3 = cv2.warpAffine(tigre, M, (600, 600))

    for x in range(300, 600):
        for y in range(300, 600):
            if mascara_7[x][y] == 255:
                crop_dst_1[x, y] = [int(dst_3[x, y][0]), int(dst_3[x, y][1]), int(dst_3[x, y][2])]
                # cv2.circle(crop_dst_2, (y, x), 2, (0, 250, 0), -1)

    # vuitena trasnformada
    dst_4 = np.float32([[300, 450], [300, 300], [450, 450]])
    src_4 = np.float32([cm_ap[1], cm_ap[2], cm_ap[4]])
    M = cv2.getAffineTransform(src_4, dst_4)
    dst_4 = cv2.warpAffine(tigre, M, (600, 600))
    for x in range(300, 600):
        for y in range(300, 600):
            if mascara_8[x][y] == 255:
                crop_dst_1[x, y] = [int(dst_4[x, y][0]), int(dst_4[x, y][1]), int(dst_4[x, y][2])]

    for i in range(600):
        cv2.circle(crop_dst_1, (515, i), 1, (255, 0, 0), -1)
        cv2.circle(crop_dst_1, (i, 515), 1, (0, 255, 0), -1)
        cv2.circle(crop_dst_1, (300, 450), 1, (0, 0, 255), -1)
    cv2.imshow('qrcode', crop_dst_1)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


elif triangles==1:
    #Detector de corners dels 3 position patterns
    corners = []
    co1 = find_one_corner(scanner.img_gray,scanner.position_patterns[0],4)
    co2 = find_one_corner(scanner.img_gray,scanner.position_patterns[1],3)
    co3 = find_one_corner(scanner.img_gray,scanner.position_patterns[2],2)
    cv2.circle(tigre, (co1), 3, (0, 0, 255), -1)
    cv2.circle(tigre, (co2), 3, (0, 255, 0), -1)
    cv2.circle(tigre, (co3), 3, (255, 0, 0), -1)
    cv2.circle(tigre, (c5[4]), 3, (255, 0, 0), -1)

    dst= np.float32([[150, 150], [450, 150], [150, 450], [450,450]])
    src = np.float32([co1,co2,co3,c5[4]])

    M = cv2.getPerspectiveTransform(src, dst)
    dst = cv2.warpPerspective(tigre, M, (600, 600))
    for i in range(600):
        cv2.circle(dst, (515,i), 1, (0, 0, 255), -1)
        cv2.circle(dst, (i,515), 1, (0, 0, 255), -1)

    # gray = np.float32(cv2.cvtColor(dst, cv2.COLOR_RGB2GRAY))
    # dst_2 = cv2.goodFeaturesToTrack(gray, 2000, 0.001, 5)
    # dst_2 = np.int0(dst_2)
    # # x, y = dst.ravel()
    # for i in dst_2:
    #     x, y = i.ravel()
    #     cv2.circle(dst, (x, y), 3, 255, -1)

    # for i in range(3):
    #     corners.append(find_corners_pp(scanner.img_gray, scanner.position_patterns[i]))
    #     cv2.circle(tigre, (corners[i][0]), 3, (0, 0, 255), -1)
    #     cv2.circle(tigre, (corners[i][1]), 3, (0, 0, 255), -1)
    #     cv2.circle(tigre, (corners[i][2]), 3, (0, 0, 255), -1)
    #     cv2.circle(tigre, (corners[i][3]), 3, (0, 0, 255), -1)
    # corners.sort()


    cv2.imshow('qrcode', dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


#cv2.drawContours(self.tigre, self.position_patterns, -1, (0, 255, 0), 3)
# OpenCV solution for performing the transform.

