from scipy.spatial import distance as dist
from imutils import perspective
from imutils import contours
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

import argparse
import imutils
import cv2
import os
import glob

data_path = "jiawei/SegmentationData5"
FIGURE_INCHES = 10

def midpoint(ptA, ptB):
	return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)


if __name__ == "__main__":
    # load the image, convert it to grayscale, and blur it slightly
    width = []
    length = []

    files = glob.glob(os.path.join(data_path, "*.jpg"))
    for i, f in enumerate(files):
        print("Doing width detection for the {} figure".format(i))
        image = cv2.imread(f)
        print(f)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (7, 7), 0)
        # perform edge detection, then perform a dilation + erosion to
        # close gaps in between object edges
        edged = cv2.Canny(gray, 50, 100)
        edged = cv2.dilate(edged, None, iterations=1)
        edged = cv2.erode(edged, None, iterations=1)
        # find contours in the edge map
        cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
	    cv2.CHAIN_APPROX_SIMPLE)
        if (len(cnts[0])==0): continue
        cnts = imutils.grab_contours(cnts)
        # sort the contours from left-to-right and initialize the
        # 'pixels per metric' calibration variable
        (cnts, _) = contours.sort_contours(cnts)
        pixelsPerMetric = None
        widthInFigure = []
        # loop over the contours individually
        for c in cnts:
            # if the contour is not sufficiently large, ignore it
            if cv2.contourArea(c) < 2000 :
                print("The {} figure is too small to be ignored".format(i))
                continue
            areaOfCnt  = cv2.contourArea(c)

            # compute the rotated bounding box of the contour
            orig = image.copy()
            box = cv2.minAreaRect(c)
            box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
            areaOfBox = cv2.contourArea(box)

            print(areaOfCnt/areaOfBox)
            if areaOfCnt/areaOfBox < 0.5:
                print("The {} figure is too irregular to be ignored".format(i))
                continue
            box = np.array(box, dtype="int")
            # order the points in the contour such that they appear
            # in top-left, top-right, bottom-right, and bottom-left
            # order, then draw the outline of the rotated bounding
            # box
            box = perspective.order_points(box)
            cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)
            # loop over the original points and draw them

            for (x, y) in box:
                cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)

                # unpack the ordered bounding box, then compute the midpoint
                # between the top-left and top-right coordinates, followed by
                # the midpoint between bottom-left and bottom-right coordinates
                (tl, tr, br, bl) = box
                (tltrX, tltrY) = midpoint(tl, tr)
                (blbrX, blbrY) = midpoint(bl, br)
                # compute the midpoint between the top-left and top-right points,
                # followed by the midpoint between the top-righ and bottom-right
                (tlblX, tlblY) = midpoint(tl, bl)
                (trbrX, trbrY) = midpoint(tr, br)
                # draw the midpoints on the image
                cv2.circle(orig, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)
                cv2.circle(orig, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)
                cv2.circle(orig, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)
                cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)
                # draw lines between the midpoints
                cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
                    (255, 0, 255), 2)
                cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
                    (255, 0, 255), 2)

                # compute the Euclidean distance between the midpoints
                dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
                dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))

                # if the pixels per metric has not been initialized, then
                # compute it as the ratio of pixels to supplied metric
                # (in this case, inches)
                # if pixelsPerMetric is None:
                    # pixelsPerMetric = dB / FIGURE_INCHES

                # compute the size of the object
                dimA = dA
                dimB = dB

                # print(dimB)
                # draw the object sizes on the image
                temp1 = max(dimA, dimB)
                temp2 = min(dimA, dimB)
                dimA = temp1
                dimB = temp2

                if dimA / dimB < 2:
                    continue
                width.append(dimA)
                length.append(dimB)

                if dimA < 80 and dimA > 60:
                    cv2.putText(orig, "This is good tobacco", (0,50), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0,0,0),2)
                else:
                    cv2.putText(orig, "This is bad tobacco", (0, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 0),
                                2)
                cv2.putText(orig, "{:.1f}pixels".format(dimB),
                    (int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,
                    0.65, (0, 0, 0), 2)
                cv2.putText(orig, "{:.1f}pixels".format(dimA),
                    (int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,
                    0.65, (0, 0, 0), 2)
                # show the output image
                # cv2.imshow("Image", orig)
                cv2.imwrite(os.path.join("Width5", "{}.jpg".format((str(i)))), orig)
                widthInFigure.append(dimB)
            # print(widthInFigure)
        width.append(np.mean(widthInFigure))

    print(width)
    mean_width = np.nanmean(width)
    # width[~pd.isnull(width)]
    print(mean_width)
    print(np.nanvar(width))
    plt.hist(width)
    plt.show()
