Почему программа закрывается, когда я закрываю всплывающее окно в tkinter? - PullRequest
0 голосов
/ 21 марта 2019

В моей программе для исправления экзаменов по камере (omr) с OpenCV2 и Python 3 он обнаруживает USB-камеру, но не программу, идущую к камере ноутбука (внутренняя часть):

import tkinter as tk
import cv2
from PIL import Image, ImageTk
from imutils.perspective import four_point_transform
from imutils import contours
import numpy as np
import argparse
import imutils
import os
import time
import sys

# the time for results name
timestr = time.strftime("%Y%m%d-%H%M%S")

# video frame
width, height = 400, 600

if cv2.VideoCapture(-1) is True:
    cap = cv2.VideoCapture(-1)
else:
    cap = cv2.VideoCapture(0)

cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
sucess, frame = cap.read()
def process_bub():
    ## cam her

    cv2.imwrite("images/test10.png", frame)

    # load the image, convert it to grayscale, blur it
    # slightly, then find edges
    cap = cv2.imread("images/test10.png")
    gray = cv2.cvtColor(cap, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(blurred, 75, 200)

    # find contours in the edge map, then initialize
    # the contour that corresponds to the document
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if imutils.is_cv2() else cnts[1]
    docCnt = None

    # ensure that at least one contour was found
    if len(cnts) > 0:
        # sort the contours according to their size in
        # descending order
        cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

        # loop over the sorted contours
        for c in cnts:
            # approximate the contour
            peri = cv2.arcLength(c, True)
            approx = cv2.approxPolyDP(c, 0.02 * peri, True)

            # if our approximated contour has four points,
            # then we can assume we have found the paper
            if len(approx) == 4:
                docCnt = approx
                break

    # apply a four point perspective transform to both the
    # original image and grayscale image to obtain a top-down
    # birds eye view of the paper
    paper = four_point_transform(cap, docCnt.reshape(4, 2))
    warped = four_point_transform(gray, docCnt.reshape(4, 2))

    # apply Otsu's thresholding method to binarize the warped
    # piece of paper
    thresh = cv2.threshold(warped, 0, 255,
                           cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

    # find contours in the thresholded image, then initialize
    # the list of contours that correspond to questions
    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if imutils.is_cv2() else cnts[1]
    questionCnts = []

    # loop over the contours
    for c in cnts:
        # compute the bounding box of the contour, then use the
        # bounding box to derive the aspect ratio
        (x, y, w, h) = cv2.boundingRect(c)
        ar = w / float(h)

        # in order to label the contour as a question, region
        # should be sufficiently wide, sufficiently tall, and
        # have an aspect ratio approximately equal to 1
        if w >= 20 and h >= 20 and ar >= 0.9 and ar <= 1.1:
            questionCnts.append(c)

    # sort the question contours top-to-bottom, then initialize
    # the total number of correct answers
    questionCnts = contours.sort_contours(questionCnts,
                                          method="top-to-bottom")[0]
    correct = 0

    # each question has 5 possible answers, to loop over the
    # question in batches of 5
    for (q, i) in enumerate(np.arange(0, len(questionCnts), 4)):
        # sort the contours for the current question from
        # left to right, then initialize the index of the
        # bubbled answer
        cnts = contours.sort_contours(questionCnts[i:i + 4])[0]
        bubbled = None

        # loop over the sorted contours
        for (j, c) in enumerate(cnts):
            # construct a mask that reveals only the current
            # "bubble" for the question
            mask = np.zeros(thresh.shape, dtype="uint8")
            cv2.drawContours(mask, [c], -1, 255, -1)

            # apply the mask to the thresholded image, then
            # count the number of non-zero pixels in the
            # bubble area
            mask = cv2.bitwise_and(thresh, thresh, mask=mask)
            total = cv2.countNonZero(mask)

            # if the current total has a larger number of total
            # non-zero pixels, then we are examining the currently
            # bubbled-in answer
            if bubbled is None or total > bubbled[0]:
                bubbled = (total, j)

        # initialize the contour color and the index of the
        # *correct* answer
        color = (0, 0, 255)
        k = ANSWER_KEY[q]

        # check to see if the bubbled answer is correct
        if k == bubbled[1]:
            color = (0, 255, 0)
            correct += 1

        # draw the outline of the correct answer on the test
        cv2.drawContours(paper, [cnts[k]], -1, color, 3)

    # grab the test taker
    score = (correct / 5.0) * 100
    degree = correct
    print("[INFO] score: {:.1f}/10".format(degree))
    cv2.putText(paper, "{:.1f}/10".format(degree), (10, 30),
                cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
    cv2.imshow("Ohod Resuls", paper)
    cv2.imwrite("results/theResult" + timestr + ".png", paper)
    cv2.waitKey(0)

# --- functions ---
ANSWER_KEY = {}


def on_button():
    for i, var in enumerate(o_vars):
        ANSWER_KEY[int(i)] = int(OPTIONS[var.get()])

    print()


# --- main ---


OPTIONS = {
    'A': '3',
    'B': '2',
    'C': '1',
    'D': '0',
}

root = tk.Tk()
root.title('OhodO')
root.bind('<Escape>', lambda e: root.quit())
lmain = tk.Label(root)
lmain.pack(side ="left")

def show_frame():
    _, frame = cap.read()
    frame = cv2.flip(frame, 1)
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    img = Image.fromarray(cv2image)
    imgtk = ImageTk.PhotoImage(image=img)
    lmain.imgtk = imgtk
    lmain.configure(image=imgtk)
    lmain.after(10, show_frame)

show_frame()


def restart_program():
    python = sys.executable
    os.execl(python, python, *sys.argv)


def dic_clear():
    ANSWER_KEY.clear()




# --- OptionMenu ---

tk.Label(root, text='Answer Keys', bg='#aaa').pack(fill='x')

o_vars = []

for i in range(10):
    var = tk.StringVar(value='- select -')
    o_vars.append(var)
    o = tk.OptionMenu(root, var, *OPTIONS)
    o.pack()

# --- others ---

b1 = tk.Button(root, text='Ok', command=on_button)
b1.pack(fill='x')
b2 = tk.Button(root, text='Clear', command=dic_clear)
b2.pack(fill='x')
b3 = tk.Button(root, text='Results', command=process_bub)
b3.pack(fill='x')
b4 = tk.Button(root, text='Close', command=root.destroy)
b4.pack(fill='x')

root.mainloop()

Проблема в этом коде:

b3 = tk.Button(root, text='Results', command=process_bub)
b3.pack(fill='x')
  1. Когда я нажимаю на кнопку «результат», программа работает отлично, то есть она дает мне результат для студенческой работы, которая была помещена перед камерой, и сохраняет изображение с результатом на нем. Тем не менее, когда я закрыл всплывающее окно с результатом на нем, программа также закрывается? Почему это?

2 - когда я щелкнул (x) в углу всплывающего окна, программа закрылась, а не всплывающее окно?!.

Эта программа (код) находится в (GPL), поэтому вы можете использовать ее бесплатно.

...