import cv2
import numpy as np
import math
from matplotlib import pyplot as plt

def __clac_intersection(line_a, line_b):
    x1_a, y1_a, x2_a, y2_a = line_a
    x1_b, y1_b, x2_b, y2_b = line_b
    A_a = y2_a - y1_a
    B_a = x1_a - x2_a
    C_a = x2_a * y1_a - x1_a * y2_a
    A_b = y2_b - y1_b
    B_b = x1_b - x2_b
    C_b = x2_b * y1_b - x1_b * y2_b
    m = A_a * B_b - A_b * B_a
    output_x = (C_b * B_a - C_a * B_b) / m
    output_y = (C_a * A_b - C_b * A_a) / m
    return (int(output_x), int(output_y))

img = cv2.imread('10076.jpg')

img_shape = img.shape
length = img_shape[0]
height = img_shape[1]

if length < height:
    height = int(800 * length / height)
    length = 800
    img = cv2.resize(img, (length, height))
else:
    length = int(800 * height / length)
    height = 800
    img = cv2.resize(img, (length, height))

image = img.copy()

# 图片锐化
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
img = cv2.filter2D(img, -1, kernel=kernel)
cv2.imshow('sharpening', img)

# 边缘保护滤波
img = cv2.edgePreservingFilter(img)
cv2.imshow('edgePreservingFilter', img)

hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

lower_skin = np.array([11,43,46])
upper_skin = np.array([34,255,255])

mask = cv2.inRange(hsv,lower_skin,upper_skin)
img = cv2.bitwise_and(img,img,mask=mask)

img_shape = img.shape
img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
dst = img_gray.copy()

# 获取图像的长宽
length = img_shape[0]
height = img_shape[1]
midlength = length / 2
midheight = height / 2
quarterL = length / 3
quarterT = height / 3
sigmaX = 2*(quarterL**2)
sigmaY = 2*(quarterT**2)

# 设置kernel
kernel = np.ones((5, 5), np.int16)
kernel[2][2] = -24

# 设置卷积核
kernel2 = np.ones((5, 5), np.int16)
kernel3 = np.ones((3, 3), np.int16)
dst = cv2.morphologyEx(img_gray, cv2.MORPH_OPEN, kernel2)

# 平滑
# 高斯
dst = cv2.blur(dst, (5, 5))
# dst = cv2.GaussianBlur(dst, (5, 5), 0)

# 锐化
blur = cv2.Laplacian(dst, cv2.CV_16S, ksize=3)
dst = cv2.convertScaleAbs(blur)

# 线性滤波,低通滤波
dst = cv2.filter2D(img_gray, -1, kernel)

# 平滑（双边滤波）
# 双边滤波
dst = cv2.bilateralFilter(dst, 9, 100, 100)

# 在二值化前进行膨胀，以增强线段
# 膨胀导致线段筛选困难
# dst = cv2.dilate(dst, kernel3)

# 二值化
ret, dst = cv2.threshold(dst, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Hough变换前的高斯赋值
# 从图像中央到边缘，逐渐降低权重
'''
for i in range(length):
    for j in range(height):
        dst[i][j] = dst[i][j] * math.exp((i-midlength)**2/sigmaX +
                                         (j-midheight)**2/sigmaY)
'''

'''
# Hough变换
lines = cv2.HoughLines(dst, 1, np.pi/180, 250)

houghLinesImage = img.copy()
print(len(lines))
for line in lines:
    rho,theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))
    if (x2-x1) == 0 :
        xielv = (y2-y1)/0.00000001
    else:
        xielv = (y2-y1)/(x2-x1)
    # if (xielv > -0.08 and xielv < 0.08)  or xielv > 8.0 or xielv < -8.0 :
        # print(xielv)
    cv2.line(houghLinesImage,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imshow('houghLinesImage', houghLinesImage)
'''

# Hough变换
thresh_min = min(dst.shape)
lines = cv2.HoughLinesP(dst, 1, np.pi / 180, 200, minLineLength=int(dst.shape[0] * 0.45), maxLineGap=int(thresh_min * 0.5))

# 过滤斜率
lines = list(filter(lambda line: True if abs(line[0][0] - line[0][2]) < 280 or abs(line[0][1] - line[0][3]) < 280 else False, lines))

houghLinesImage = img.copy()
for line in lines:
    x1,y1,x2,y2 = line[0]
    cv2.line(houghLinesImage,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imshow('houghLinesImage', houghLinesImage)


if lines is not None:
    lines_vertical = filter(lambda line: True if abs(line[0][1] - line[0][3]) > length * 0.2 else False, lines)
    lines_horizontal  = filter(lambda line: True if abs(line[0][0] - line[0][2]) > height * 0.2 else False, lines)

    # lines_vertical = filter(isVerticalLine, lines_vertical)
    # lines_horizontal = filter(isHorizontalLine, lines_horizontal)

    lines_vertical = sorted(lines_vertical, key=lambda line: (line[0][0] + line[0][2]) / 2)
    lines_horizontal = sorted(lines_horizontal , key=lambda line: (line[0][1] + line[0][3]) / 2)

    if len(lines_vertical) > 2 and len(lines_horizontal) > 2:
        houghLines = [lines_vertical[0][0], lines_horizontal [0][0], lines_vertical[-1][0], lines_horizontal [-1][0]]

        houghEdgeImage = image.copy()
        cv2.line(houghEdgeImage,(houghLines[0][0],houghLines[0][1]),(houghLines[0][2],houghLines[0][3]),(255,0,0),2)
        cv2.line(houghEdgeImage,(houghLines[2][0],houghLines[2][1]),(houghLines[2][2],houghLines[2][3]),(0,255,0),2)
        cv2.line(houghEdgeImage,(houghLines[1][0],houghLines[1][1]),(houghLines[1][2],houghLines[1][3]),(0,0,255),2)
        cv2.line(houghEdgeImage,(houghLines[3][0],houghLines[3][1]),(houghLines[3][2],houghLines[3][3]),(255,255,0),2)
        cv2.imshow('houghEdge', houghEdgeImage)

        p1 = __clac_intersection((houghLines[0][0],houghLines[0][1], houghLines[0][2],houghLines[0][3]), (houghLines[1][0],houghLines[1][1], houghLines[1][2],houghLines[1][3]))
        p2 = __clac_intersection((houghLines[1][0],houghLines[1][1], houghLines[1][2],houghLines[1][3]), (houghLines[2][0],houghLines[2][1], houghLines[2][2],houghLines[2][3]))
        p3 = __clac_intersection((houghLines[2][0],houghLines[2][1], houghLines[2][2],houghLines[2][3]), (houghLines[3][0],houghLines[3][1], houghLines[3][2],houghLines[3][3]))
        p4 = __clac_intersection((houghLines[3][0],houghLines[3][1], houghLines[3][2],houghLines[3][3]), (houghLines[0][0],houghLines[0][1], houghLines[0][2],houghLines[0][3]))

        warpPerspectiveImage = image.copy()
        pts1 = np.float32([p1,p2,p4,p3])
        pts2 = np.float32([[0,0],[800,0],[0,800],[800,800]])
        M = cv2.getPerspectiveTransform(pts1,pts2)
        dst = cv2.warpPerspective(warpPerspectiveImage,M,(800,800))
        cv2.imshow('warpPerspective', dst)


# 利用方差进行平行线的判断
# 近邻生长法
# Hough变换
# 首先找到水平的范围，上边界为rho最大，theta最小，下边界为rho最小，theta最大（<90)
ThetaMIN2 = 180
ThetaMIN = 180
ThetaMAX = -1
ThetaMAX2 = -1
RhoMAX = -1
RhoMAX2 = -1
RhoMIN = 1000
RhoMIN2 = 1000
up = 0
bot = 0
up2 = 0
bot2 = 0

'''
for i in range(int(lines[0].size/2)):
    # 遍历全部点集
    r, t = lines[0][i]
    print(lines[0][i])
    t = t / np.pi*180
    if t < 90:
        # theta < 90，属于水平范围
        if t > ThetaMAX:
            ThetaMAX = t
            up = i
        if r > RhoMAX:
            RhoMAX = r
            bot = i
    else:
        if t > ThetaMAX2:
            ThetaMAX2 = t
            up2 = i
        if t < ThetaMIN2:
            ThetaMIN2 = t
            bot2 = i

result = [up, bot, up2, bot2]
print(result)
# Hough变换
xtheta = []
yrho = []
for rho, theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))
    # if theta < 0.5:
    xtheta.append(theta / np.pi * 180)
    yrho.append(rho)
    cv2.line(img, (x1, y1), (x2, y2), (255, 255, 0), 2)

print(result)
for i in result:
    rho = lines[0][i][0]
    theta = lines[0][i][1]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))
    cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 10)
'''

# 计算最有可能的两条best

# 显示
# plt.subplot(1, 2, 1), plt.imshow(dst, 'gray')

plt.subplot(1, 3, 1), plt.imshow(dst, 'gray')
plt.title('test')
plt.xticks([]), plt.yticks([])

plt.subplot(1, 3, 2), plt.imshow(img_gray, 'gray')
plt.title('ori')
plt.xticks([]), plt.yticks([])

# plt.subplot(1, 4, 3), plt.scatter(xtheta, yrho, c='b', marker='o')
# plt.title('Hough')
# plt.xlabel('X'), plt.ylabel('Y')

plt.subplot(1, 3, 3), plt.imshow(img)
plt.title('Lines')
plt.xticks([]), plt.yticks([])

plt.show()
