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

@Modify Time      @Author    @Version    @Desciption
------------      -------    --------    -----------
2024/1/7 22:57   Pengyu Zhang      1.0         None
'''

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import cv2
import numpy as np
from matplotlib import pyplot as plt

def preprocess_image(image,size,blur):
    # 将图像调整为固定大小
    # image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    if size !=-1:
        image = cv2.resize(image, (size, size), interpolation=cv2.INTER_AREA)
    if size == -1:
        image = cv2.cvtColor(np.array(image), cv2.COLOR_BGR2GRAY)
    if blur:
        kernel_size = 3
        image = cv2.GaussianBlur(image, (kernel_size, kernel_size), sigmaX=1, sigmaY=0)
    return image
def clos_open(input,B_p):
    _, binary_image = cv2.threshold(input, B_p, 255, cv2.THRESH_BINARY)
    # 定义结构元素（内核）
    kernel = np.ones((3, 3), np.uint8)

    # 开运算
    opening = cv2.morphologyEx(binary_image, cv2.MORPH_OPEN, kernel)

    # 定义结构元素（内核）
    kernel = np.ones((3, 3), np.uint8)
    # 闭运算
    closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)

    return closing


def img_angle(input):
    # canny边缘检测
    eroded_canny = cv2.Canny(input, 50, 255, apertureSize=3)
    contours, hierarchy = cv2.findContours(eroded_canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 寻找最大元素
    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

    # 拟合旋转矩形
    cnt = contours[index]
    rect = cv2.minAreaRect(cnt)
    angle = rect[2]
    box = cv2.boxPoints(rect)

    box = np.int0(box)

    # 对点按照y坐标排序（最上和最下的点）
    box = box[box[:, 1].argsort()]

    # 上边的两个点按照x坐标排序（决定左上和右上）
    top_two = box[:2]
    top_two = top_two[top_two[:, 0].argsort()]

    # 下边的两个点按照x坐标排序（决定左下和右下）
    bottom_two = box[2:]
    bottom_two = bottom_two[bottom_two[:, 0].argsort()]

    # 重新组合为左上、右上、右下、左下的顺序
    ordered_box = np.array([top_two[0], top_two[1], bottom_two[1], bottom_two[0]])

    return angle,ordered_box

def angel_affine(input,angle):
    height, width = np.array(input).shape
    center = (width // 2, height // 2)
    if angle is not None and angle != 0.0:
        if angle > 45.0:
            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)

    return output


def merge_overlapping_rectangles(rectangles):
    if len(rectangles) <= 1:
        return rectangles

    merged_rectangles = []
    for rect in sorted(rectangles, key=lambda x: x[2]*x[3], reverse=True):
        x, y, w, h = rect
        if not any((x < x2 + w2 and x + w > x2 and y < y2 + h2 and y + h > y2) for x2, y2, w2, h2 in merged_rectangles):
            merged_rectangles.append(rect)
    return merged_rectangles


def roi2_detector(input,min_area_threshold):
    # 使用 Canny 边缘检测
    edges = cv2.Canny(input, 50, 255, apertureSize=3)

    # 寻找轮廓
    contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 临时存储矩形
    temp_rectangles = []

    # 识别矩形轮廓
    for contour in contours:
        # 轮廓近似
        epsilon = 0.001 * cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, epsilon, True)

        if len(approx) >= 4:
            x, y, w, h = cv2.boundingRect(approx)
            aspect_ratio = w / float(h)
            area_contour = cv2.contourArea(contour)
            if aspect_ratio >= 0.75 and aspect_ratio < 1.2 and min_area_threshold < area_contour < 15000:
                area_bounding_rect = w * h
                area_ratio = area_contour / area_bounding_rect
                if 0.75 < area_ratio < 1.05:
                    temp_rectangles.append((x, y, w, h))

    # 合并重叠的方框
    merged_rectangles = merge_overlapping_rectangles(temp_rectangles)

    # 选择并绘制最大的方框
    if merged_rectangles:
        outermost_rectangle = max(merged_rectangles, key=lambda x: x[2]*x[3])
        rectangle_count = 1
        return outermost_rectangle
    else:
        return None
from PIL import Image

def roi_img_processing(input):
    input_ray = cv2.cvtColor(np.array(input), cv2.COLOR_BGR2GRAY)
    img_resize = preprocess_image(input_ray, 128, blur=False)
    img_closing = clos_open(img_resize,B_p=50)  # 闭运算
    min_area_threshold=6500
    roi_coordinate = roi2_detector(img_closing,min_area_threshold)
    if roi_coordinate is None:
        img_closing = clos_open(img_resize, B_p=100)  # 闭运算
        roi_coordinate = roi2_detector(img_closing,min_area_threshold)
        if roi_coordinate is None:
            return None
    x, y, w, h = roi_coordinate
    # 截取图像
    input_fix = img_resize[y+1:y-1 + h, x+1:x-1 + w]
    output = preprocess_image(input_fix, 32, blur=True)

    return output

def roi_detect(input):
    size = 128
    height, width, _ = input.shape

    if height < size:
        img_resize = cv2.resize(np.array(input), (size, size), interpolation=cv2.INTER_AREA)
    else:
        img_resize = cv2.resize(np.array(input), (size, size), interpolation=cv2.INTER_LINEAR)
    image_gay = cv2.cvtColor(img_resize, cv2.COLOR_BGR2GRAY)
    min_area_threshold = 1000
    img_closing = clos_open(image_gay, B_p=50)  # 闭运算
    roi_coordinate = roi2_detector(img_closing,min_area_threshold)

    if roi_coordinate is None :
        img_closing = clos_open(img_resize, B_p=100)  # 闭运算
        roi_coordinate = roi2_detector(img_closing,min_area_threshold)
        # print('150')
    if roi_coordinate is None :
        img_closing = clos_open(img_resize, B_p=150)  # 闭运算
        roi_coordinate = roi2_detector(img_closing,min_area_threshold)
        # print('100')
    if roi_coordinate is None :
        img_closing = clos_open(img_resize, B_p=120)  # 闭运算
        roi_coordinate = roi2_detector(img_closing,min_area_threshold)
    if roi_coordinate is None:
        img_closing = clos_open(img_resize, B_p=75)  # 闭运算
        roi_coordinate = roi2_detector(img_closing,min_area_threshold)
    if roi_coordinate is None:
        return None
    x, y, w, h = roi_coordinate
    # 截取图像
    input_fix = img_resize[y + 1:y - 1 + h, x + 1:x - 1 + w]
    input_fix = Image.fromarray(np.uint8(input_fix))
    return input_fix
def roi_minAreaRect(input):
    img_closing = clos_open(input)  # 闭运算
    _, box = img_angle(img_closing)  # 图像偏差角度
    return box



