#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File        :   qr_detection.py
@Contact     :   zpyovo@hotmail.com
@License     :   (C)Copyright 2018-2019, Lab501-TransferLearning-SCUT
@Description :

@Modify Time      @Author    @Version    @Desciption
------------      -------    --------    -----------
2022/4/22 09:08   Pengyu Zhang      1.0         None
'''

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from PIL import Image, ImageEnhance
import numpy as np
import cv2


def solution_1_1(img, detector):
    # 亮度处理
    birght_img = ImageEnhance.Brightness(img)
    birght_img = birght_img.enhance(2)
    birght_img = np.array(birght_img)
    res, points = detector.detectAndDecode(birght_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_1_2(img, detector):
    # 亮度处理
    birght_img = ImageEnhance.Brightness(img)
    birght_img = birght_img.enhance(3)
    birght_img = np.array(birght_img)
    res, points = detector.detectAndDecode(birght_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_2_1(img, detector):
    # #对比度增强 + 亮度处理
    contrast_img = ImageEnhance.Contrast(img)
    contrast_img = contrast_img.enhance(1.5)
    birght_img = ImageEnhance.Brightness(contrast_img)
    birght_img = birght_img.enhance(2)
    birght_img = np.array(birght_img)
    res, points = detector.detectAndDecode(birght_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_2_2(img, detector):
    # #对比度增强 + 亮度处理
    contrast_img = ImageEnhance.Contrast(img)
    contrast_img = contrast_img.enhance(1.5)
    birght_img = ImageEnhance.Brightness(contrast_img)
    birght_img = birght_img.enhance(3)
    birght_img = np.array(birght_img)
    res, points = detector.detectAndDecode(birght_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(birght_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_3_1(img, detector):
    # # 亮度处理 + 对比度增强

    birght_img = ImageEnhance.Brightness(img)
    birght_img = birght_img.enhance(2)
    contrast_img = ImageEnhance.Contrast(birght_img)
    contrast_img = contrast_img.enhance(1.5)
    contrast_img = np.array(contrast_img)
    res, points = detector.detectAndDecode(contrast_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(contrast_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(contrast_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_3_2(img, detector):
    # 亮度处理 + 对比度增强

    birght_img = ImageEnhance.Brightness(img)
    birght_img = birght_img.enhance(3)
    contrast_img = ImageEnhance.Contrast(birght_img)
    contrast_img = contrast_img.enhance(1.5)
    contrast_img = np.array(contrast_img)
    res, points = detector.detectAndDecode(contrast_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(contrast_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(contrast_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_4_1(img, detector):
    # 亮度处理 + 对比度增强 + 锐化
    birght_img = ImageEnhance.Brightness(img)
    birght_img = birght_img.enhance(2)
    contrast_img = ImageEnhance.Contrast(birght_img)
    contrast_img = contrast_img.enhance(1.5)
    sharpness_img = ImageEnhance.Sharpness(contrast_img)
    sharpness_img = sharpness_img.enhance(1.5)
    sharpness_img = np.array(sharpness_img)
    res, points = detector.detectAndDecode(sharpness_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(sharpness_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(sharpness_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_4_2(img, detector):
    # 亮度处理 + 对比度增强 + 锐化
    birght_img = ImageEnhance.Brightness(img)
    birght_img = birght_img.enhance(3)
    contrast_img = ImageEnhance.Contrast(birght_img)
    contrast_img = contrast_img.enhance(1.5)
    sharpness_img = ImageEnhance.Sharpness(contrast_img)
    sharpness_img = sharpness_img.enhance(1.5)
    sharpness_img = np.array(sharpness_img)
    res, points = detector.detectAndDecode(sharpness_img)
    if len(res) == 0:
        samll_img = cv2.resize(np.array(sharpness_img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
        input = np.array(samll_img)
        res, points = detector.detectAndDecode(input)
        if len(res) == 0:
            samll_img = cv2.resize(np.array(sharpness_img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
            input = np.array(samll_img)
            res, points = detector.detectAndDecode(input)
            if len(res) == 0:
                return None, None
            else:
                return res, points[0] * 8
        return res, points[0] * 4
    return res, points[0] * 1


def solution_5(img, detector):
    # 缩放X4
    samll_img = cv2.resize(np.array(img), None, fx=1 / 4, fy=1 / 4, interpolation=cv2.INTER_CUBIC)
    input = np.array(samll_img)
    res, points = detector.detectAndDecode(input)
    if len(res) == 0:
        return None, None
    else:
        return res, points[0] * 4


def solution_6(img, detector):
    # 缩放X8
    samll_img = cv2.resize(np.array(img), None, fx=1 / 8, fy=1 / 8, interpolation=cv2.INTER_CUBIC)
    input = np.array(samll_img)
    res, points = detector.detectAndDecode(input)
    if len(res) == 0:
        return None, None
    else:
        return res, points[0] * 8


def rotation_waffine(rotation_region, input):
    # 亮度处理
    birght_img = ImageEnhance.Brightness(rotation_region)
    birght_img = birght_img.enhance(5)

    # 灰度二值化
    img_grey = cv2.cvtColor(np.array(birght_img), cv2.COLOR_BGR2GRAY)
    ret2, thresh = cv2.threshold(img_grey, 0, 255,
                                 cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 腐蚀
    # OpenCV定义的结构矩形元素
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 50))
    eroded = cv2.erode(thresh, kernel)

    # canny边缘检测
    eroded_canny = cv2.Canny(eroded, 100, 300)
    contours, hierarchy = cv2.findContours(eroded_canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # canny_img = np.zeros((np.array(birght_img).shape[0], np.array(birght_img).shape[1], 3), np.uint8) + 255
    # canny_img = cv2.drawContours(canny_img, contours, -1, (0, 255, 0), 3)

    # 寻找最大元素
    k = 0
    index = 0
    if len(contours) != 0:
        for i in range(len(contours)):
            j = contours[i].size
            if j > k:
                k = j
                index = i
    else:
        return input

    # 拟合旋转矩形
    cnt = contours[index]
    rect = cv2.minAreaRect(cnt)
    angle = rect[2]
    # box = cv2.boxPoints(rect)
    # box = np.int0(box)
    # rect_img = cv2.drawContours(canny_img, [box], 0, (0, 0, 255), 2)

    # 根据角度差计算仿射矩阵
    height, width, _ = np.array(input).shape
    center = (width // 2, height // 2)
    if angle != 0.0:
        if angle > 45.0:
            angle = angle - 90
        # angle = angle - 90
        # rotate page if not straight relative to QR code
        M = cv2.getRotationMatrix2D(center, angle, 1.0)
        output = cv2.warpAffine(np.array(input), M, (width, height), flags=cv2.INTER_CUBIC,
                                borderMode=cv2.BORDER_REPLICATE)
        output = Image.fromarray(output)

        output = output.convert("RGB")
    else:
        output = input

    return output

def rotation_region_crop(input,points):
    input = np.array(input)
    x1 = int(points[0, 0])
    y1 = int(points[0, 1])
    x2 = int(points[1, 0])
    y2 = int(points[1, 1])
    x_a = x1 - int((x2 - x1) * 0.1)
    x_b = x2 + int((x2 - x1) * 0.1)
    y_a = y1 - int((y2 - y1) * 0.1)
    y_b = y2 + int((y2 - y1) * 0.1)
    if x_a < 0:
        x_a = 0
    if y_a < 0:
        y_a = 0
    if x_b >= input.shape[1]:
        x_b = input.shape[1]
    if y_b >= input.shape[0]:
        y_b = input.shape[0]

    top_size, bottom_size, left_size, right_size = (50, 50, 50, 50)
    rotation_region = cv2.copyMakeBorder(input[y_a:y_b, x_a:x_b], top_size, bottom_size, left_size, right_size,
                                         borderType=cv2.BORDER_REPLICATE, value=0)
    return  rotation_region

def qr_detetor(input, detector):
    success = False
    if not success:
        res, points = solution_1_1(input, detector)

        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input,points)
            img = rotation_waffine(Image.fromarray(rotation_region),input)
            # img = input
            # print('solution_1_1')

            return res, points, img

    if not success:
        res, points = solution_1_2(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            # print('solution_1_2')
            return res, points, img

    if not success:
        res, points = solution_5(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_5')
            return res, points, img

    if not success:
        res, points = solution_6(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_6')
            return res, points, img

    if not success:
        res, points = solution_2_1(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_2_1')
            return res, points, img

    if not success:
        res, points = solution_2_2(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_2_2')
            return res, points, img

    if not success:
        res, points = solution_3_1(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_3_1')
            return res, points, img

    if not success:
        res, points = solution_3_2(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_3_2')
            return res, points, img

    if not success:
        res, points = solution_4_1(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_4_1')
            return res, points, img

    if not success:
        res, points = solution_4_2(input, detector)
        if res == None:
            success = False
        else:
            success = True
            rotation_region = rotation_region_crop(input, points)
            img = rotation_waffine(Image.fromarray(rotation_region), input)
            # img = input
            print('solution_4_2')
            return res, points, img

    if success is False:
        return None, None, None
