from keras.models import load_model
from helpers import resize_to_fit
from imutils import paths
import numpy as np
import imutils
import cv2
import pickle
import os
import os.path
import cv2
import glob
import datetime as dt

time_start = dt.datetime.now()
MODEL_FILENAME = "captcha_model.hdf5"
MODEL_LABELS_FILENAME = "model_labels.dat"
CAPTCHA_IMAGE_FOLDER = "test"


f=open("codes.txt",'r')
a=f.read().splitlines()

# Load up the model labels (so we can translate model predictions to actual letters)
with open(MODEL_LABELS_FILENAME, "rb") as f:
    lb = pickle.load(f)

# Load the trained neural network
model = load_model(MODEL_FILENAME)

# Grab some random CAPTCHA images to test against.
# In the real world, you'd replace this section with code to grab a real
# CAPTCHA image from a live website.
# captcha_image_files = list(paths.list_images(CAPTCHA_IMAGE_FOLDER))
# captcha_image_files = np.random.choice(captcha_image_files, size=(10,), replace=False)

# loop over the image paths
captcha_image_files = glob.glob(os.path.join(CAPTCHA_IMAGE_FOLDER, "*"))
counts = {}
k=0
# loop over the image paths
for (i, captcha_image_file) in enumerate(captcha_image_files):
    if i%100 == 0:
        print("i="+str(i)+" & k="+str(k))
    # Load the image and convert it to grayscale
    # imagek = cv2.imread(captcha_image_file)
    # image2 = cv2.cvtColor(imagek,cv2.COLOR_BGR2HSV)
    filename = os.path.basename(captcha_image_file)
    y1=filename.replace("image","")
    y2=y1.replace(".png","")
    ind=int(y2)
    captcha_correct_text = a[ind]
    # # print("Correct text is "+captcha_correct_text)
    # # cv2.imshow("hi",image2)
    # pixel= image2[0, 0]
    # pixel2 = image2[149, 599]
    # if pixel.all() != pixel2.all():
    #     count = count + 1
    # pixel3 = image2[0, 1]
    # #TO FIND HSL OF MIDLINE DEVIATING FROM [_,76,255]
    # # for i in range(150):
    # #     pixell = image2[i,140]
    # #     if(pixell[1] != 76 or pixell[2] != 255):
    # #         print(i)
    # #         print(pixell)
    # ##Cahnge all non compliant pixels to background
    # count127=0
    # count76_255=0
    # count_other=0

    # for i in range(150):
    #     for j in range(600):
    #         pixelij = image2[i, j]
    #         # print("Pixel = ", pixelij[0], pixelij[1], pixelij[2])
    #         if (pixelij[1] == 127): # letters
    #             # count127 = count127 + 1
    #             # print("Pixel = ", pixelij[0], pixelij[1], pixelij[2])
    #             image2[i, j][2] = 0
    #             image2[i, j][1] = 0
    #             image2[i, j][0] = 0
    #             continue
    #         elif (pixelij[1] == 76 and pixelij[2] ==255): # background
    #             # image2[i, j] = [0,0,0]
    #             # count76_255 = count76_255 + 1
    #             image2[i, j][2] = 255
    #             image2[i, j][1] = 255
    #             image2[i, j][0] = 179
    #             continue
    #         else: # background pixel
    #             # image2[i, j] = pixel
    #             # count_other = count_other + 1
    #             image2[i, j] = pixel
    image = cv2.imread(captcha_image_file)
    image2 = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
    image2[:,:,0] = np.where(image2[:, :, 1] == 127, 0, image2[:, :, 0])
    image2[:,:,1] = np.where(image2[:, :, 1] == 127, 0, image2[:, :, 1])
    image2[:,:,2] = np.where(image2[:, :, 1] == 127, 0, image2[:, :, 2])

    image2[:,:,0] = np.where(np.logical_and(image2[:, :, 1] == 76, image2[:, :, 2] == 255), 179, image2[:, :, 0])
    image2[:,:,1] = np.where(np.logical_and(image2[:, :, 1] == 76, image2[:, :, 2] == 255), 255, image2[:, :, 1])
    image2[:,:,2] = np.where(np.logical_and(image2[:, :, 1] == 76, image2[:, :, 2] == 255), 255, image2[:, :, 2])
    
    cond = np.logical_and(np.logical_and(image2[:, :, 1] != 76, image2[:, :, 2] != 255), image2[:, :, 1] != 127)
    image2[:,:,0] = np.where(cond, 179, image2[:, :, 0])
    image2[:,:,1] = np.where(cond, 255, image2[:, :, 1])
    image2[:,:,2] = np.where(cond, 255, image2[:, :, 2])
    # converting the image into balck and white
    image = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY)
    # image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Add some extra padding around the image
    # image = cv2.copyMakeBorder(image_bw, 20, 20, 20, 20, cv2.BORDER_REPLICATE)

    # threshold the image (convert it to pure black and white)
    thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

    # find the contours (continuous blobs of pixels) the image
    contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # Hack for compatibility with different OpxenCV versions
    contours = contours[1] if imutils.is_cv3() else contours[0]

    letter_image_regions = []

    # Now we can loop through each of the four contours and extract the letter
    # inside of each one
    for contour in contours:
        # Get the rectangle that contains the contour
        (x, y, w, h) = cv2.boundingRect(contour)

        # Compare the width and height of the contour to detect letters that
        # are conjoined into one chunk
        if w<15 or h<50:
            continue
        # if w / h > 1.25:
        #     # This contour is too wide to be a single letter!
        #     # Split it in half into two letter regions!
        #     half_width = int(w / 2)
        #     letter_image_regions.append((x, y, half_width, h))
        #     letter_image_regions.append((x + half_width, y, half_width, h))
        else:
            # This is a normal letter by itself
            letter_image_regions.append((x, y, w, h))

    # If we found more or less than 4 letters in the captcha, our letter extraction
    # didn't work correcly. Skip the image instead of saving bad training data!
    # if len(letter_image_regions) != 4:
    #     continue

    # Sort the detected letter images based on the x coordinate to make sure
    # we are processing them from left-to-right so we match the right image
    # with the right letter
    letter_image_regions = sorted(letter_image_regions, key=lambda x: x[0])

    # Create an output image and a list to hold our predicted letters
    output = cv2.merge([image] * 3)
    predictions = []

    # loop over the lektters
    for letter_bounding_box in letter_image_regions:
        # Grab the coordinates of the letter in the image
        x, y, w, h = letter_bounding_box

        # Extract the letter from the original image with a 2-pixel margin around the edge
        letter_image = image[y - 2:y + h + 2, x - 2:x + w + 2]

        # Re-size the letter image to 20x20 pixels to match training data
        letter_image = resize_to_fit(letter_image, 20, 20)

        # Turn the single image into a 4d list of images to make Keras happy
        letter_image = np.expand_dims(letter_image, axis=2)
        letter_image = np.expand_dims(letter_image, axis=0)

        # Ask the neural network to make a prediction
        prediction = model.predict(letter_image)

        # Convert the one-hot-encoded prediction back to a normal letter
        letter = lb.inverse_transform(prediction)[0]
        predictions.append(letter)

        # draw the prediction on the output image
        # cv2.rectangle(output, (x - 2, y - 2), (x + w + 4, y + h + 4), (0, 255, 0), 1)
        # cv2.putText(output, letter, (x - 5, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.55, (0, 255, 0), 2)

    # Print the captcha's text
    captcha_text = "".join(predictions)
    # print("CAPTCHA text is: "+format(captcha_text))
    if captcha_correct_text == captcha_text:
        k=k+1
    else:
        print("  Predicted is "+captcha_text + "Correct is" + captcha_correct_text)
        # cv2.imshow("Output", output)
        # cv2.waitKey()
    # Show the annotated image
    # cv2.imshow("Output", output)
    # cv2.waitKey()
# print("i=",i,"k=",k)
time_end = dt.datetime.now()
print(" time taken ", time_end - time_start, " time")