def __init__(self, model_path, per=50):
     self.count = Queue(1000)
     self.ct = CentroidTracker(maxDisappeared=10, maxDistance=50)
     self.face_detector = DETECTOR()
     self.trackers = []
     self.trackableObjects = {}
     self.per = Value('i', per)
     self.up = 0
     self.down = 0
示例#2
0
 def __init__(self, threadID, src, floor):
     threading.Thread.__init__(self)
     self.threadID = threadID
     self.name = src
     self.floor = floor
     self.door = 1
     # self.cap = cv.VideoCapture(src)
     self.net = cv.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
     self.net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
     self.net.setPreferableTarget(cv.dnn.DNN_TARGET_OPENCL)
     self.ct = CentroidTracker(maxDisappeared=40, maxDistance=50)
     self.trackableObjects = {}
     self.totalDown = 0
     self.totalUp = 0
     self.totalU = 0
     self.totalD = 0
class People_counting:
    def __init__(self, model_path, per=50):
        self.count = Queue(1000)
        self.ct = CentroidTracker(maxDisappeared=10, maxDistance=50)
        self.face_detector = DETECTOR()
        self.trackers = []
        self.trackableObjects = {}
        self.per = Value('i', per)
        self.up = 0
        self.down = 0

    def people_count(self, frame, per=50):
        (boxes, scores) = self.face_detector.detection(frame,
                                                       score_threshold=0.65)
        print(boxes, scores)
        self.per.value = per
        if len(boxes) > 0:
            for box in boxes:
                box = list(map(int, box))
                cv.rectangle(frame, (box[0], box[1]),
                             (box[0] + box[2], box[1] + box[3]), (0, 255, 0),
                             1)
            self.postprocess(frame, boxes)

        cv.imshow("Frame", frame)
        cv.waitKey(1)
        return

    def postprocess(self, frame, outs):
        frameHeight = frame.shape[0]
        frameWidth = frame.shape[1]
        rects = []

        for box in outs:
            box = list(map(int, box))
            top = box[1]
            left = box[0]
            height = box[3]
            width = box[2]
            rects.append((left, top, left + width, top + height))
            #rects.append((left, top, right, bottom))
        objects = self.ct.update(rects)
        self.counting(objects)

    def counting(self, objects):
        frameHeight = int(self.per.value / 100 * frame.shape[0])
        print("============================== Line Value {}    {}".format(
            frameHeight, self.per.value))
        print(
            "====================================== up : {}  down : {}".format(
                self.up, self.down))
        if frame.shape[0] - frameHeight < 0 or frameHeight < 30:
            print(
                "[error] Select other value for line percentage setting to 50% default of frame width"
            )
            frameHeight = frame.shape[0] // 2

        frameWidth = frame.shape[1]
        for (objectID, centroid) in objects.items():
            to = self.trackableObjects.get(objectID, None)

            if to is None:
                to = TrackableObject(objectID, centroid)

            else:
                y = [c[1] for c in to.centroids]
                direction = centroid[1] - np.mean(y)
                to.centroids.append(centroid)

                if not to.counted:
                    #print(next( range(frameHeight//2 - 30, frameHeight//2 + 30)))
                    #print(to.counted,direction,centroid[1] in range(frameHeight - 30, frameHeight + 30))
                    if direction < 0 and centroid[1] in range(
                            frameHeight - 30, frameHeight + 30):
                        #self.totalUp += 1
                        s = datetime.datetime.now()
                        print(1, "......................", s)
                        self.count.put([1, s])
                        #print("1",datetime.datetime.now())
                        to.counted = True
                        self.up += 1

                    elif direction > 0 and centroid[1] in range(
                            frameHeight - 30, frameHeight + 30):
                        #self.totalDown += 1
                        s = datetime.datetime.now()
                        print(0, "......................", s)
                        #self.count
                        self.count.put([0, s])
                        #print(datetime.datetime.now())
                        to.counted = True
                        self.down += 1
                #try:
                #    #print("counted :", self.count.get_nowait())
                #except:
                #    pass
            self.trackableObjects[objectID] = to
net = cv.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv.dnn.DNN_TARGET_OPENCL)

# initialize the video writer
writer = None
 
# initialize the frame dimensions (we'll set them as soon as we read
# the first frame from the video)
W = None
H = None
 
# instantiate our centroid tracker, then initialize a list to store
# each of our dlib correlation trackers, followed by a dictionary to
# map each unique object ID to a TrackableObject
ct = CentroidTracker(maxDisappeared=40, maxDistance=50)
trackers = []
trackableObjects = {}
 
# initialize the total number of frames processed thus far, along
# with the total number of objects that have moved either up or down
totalDown = 0
totalUp = 0

# Get the names of the output layers
def getOutputsNames(net):
    # Get the names of all the layers in the network
    layersNames = net.getLayerNames()
    # Get the names of the output layers, i.e. the layers with unconnected outputs
    return [layersNames[i[0] - 1] for i in net.getUnconnectedOutLayers()]
示例#5
0
class myThread(threading.Thread):
    maxRetries = 20

    def __init__(self, threadID, src, floor):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = src
        self.floor = floor
        self.door = 1
        # self.cap = cv.VideoCapture(src)
        self.net = cv.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
        self.net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
        self.net.setPreferableTarget(cv.dnn.DNN_TARGET_OPENCL)
        self.ct = CentroidTracker(maxDisappeared=40, maxDistance=50)
        self.trackableObjects = {}
        self.totalDown = 0
        self.totalUp = 0
        self.totalU = 0
        self.totalD = 0

    def attemptRead(self, cvVideo):
        threadLock.acquire()
        (isRead, cvImage) = cvVideo.read()
        threadLock.release()
        if isRead == False:
            count = 1
            while isRead == False and count < myThread.maxRetries:
                threadLock.acquire()
                (isRead, cvImage) = cvVideo.read()
                threadLock.release()
                # print(self.name+' try no: ',count)
                count += 1
        return (isRead, cvImage)

    # Get the names of the output layers
    def getOutputsNames(self):
        # Get the names of all the layers in the network
        layersNames = self.net.getLayerNames()
        # Get the names of the output layers, i.e. the layers with unconnected outputs
        return [
            layersNames[i[0] - 1] for i in self.net.getUnconnectedOutLayers()
        ]


# Remove the bounding boxes with low confidence using non-maxima suppression

    def postprocess(self, cap, frame, outs):
        frameHeight = frame.shape[0]
        frameWidth = frame.shape[1]

        rects = []

        # Scan through all the bounding boxes output from the network and keep only the
        # ones with high confidence scores. Assign the box's class label as the class with the highest score.
        classIds = []
        confidences = []
        boxes = []
        for out in outs:
            for detection in out:
                scores = detection[5:]
                classId = np.argmax(scores)
                confidence = scores[classId]
                if confidence > confThreshold:
                    center_x = int(detection[0] * frameWidth)
                    center_y = int(detection[1] * frameHeight)
                    width = int(detection[2] * frameWidth)
                    height = int(detection[3] * frameHeight)
                    left = int(center_x - width / 2)
                    top = int(center_y - height / 2)
                    classIds.append(classId)
                    confidences.append(float(confidence))
                    boxes.append([left, top, width, height])

        # Perform non maximum suppression to eliminate redundant overlapping boxes with
        # lower confidences.
        indices = cv.dnn.NMSBoxes(boxes, confidences, confThreshold,
                                  nmsThreshold)
        for i in indices:
            i = i[0]
            box = boxes[i]
            left = box[0]
            top = box[1]
            width = box[2]
            height = box[3]
            # Class "person"
            if classIds[i] == 0:
                rects.append((left, top, left + width, top + height))
                # use the centroid tracker to associate the (1) old object
                # centroids with (2) the newly computed object centroids
                objects = self.ct.update(rects)
                cv.rectangle(frame, (left, top), (left + width, top + height),
                             (255, 178, 50), 2)
                self.counting(cap, frame, objects, left, top, left + width,
                              top + height)

                #drawPred(classIds[i], confidences[i], left, top, left + width, top + height)

    def counting(self, cap, frame, objects, left, top, right, bottom):
        frameHeight = frame.shape[0]
        frameWidth = frame.shape[1]

        # loop over the tracked objects
        for (objectID, centroid) in objects.items():
            # check to see if a trackable object exists for the current
            # object ID
            to = self.trackableObjects.get(objectID, None)

            # if there is no existing trackable object, create one
            if to is None:
                to = TrackableObject(objectID, centroid)

            # otherwise, there is a trackable object so we can utilize it
            # to determine direction
            else:
                # the difference between the y-coordinate of the *current*
                # centroid and the mean of *previous* centroids will tell
                # us in which direction the object is moving (negative for
                # 'up' and positive for 'down')
                y = [c[1] for c in to.centroids]
                direction = centroid[1] - np.mean(y)
                to.centroids.append(centroid)

                # check to see if the object has been counted or not
                if not to.counted:
                    # if the direction is negative (indicating the object
                    # is moving up) AND the centroid is above the center
                    # line, count the object

                    if direction < 0 and centroid[1] in range(
                            frameHeight // 2 - 30, frameHeight // 2 + 30):
                        self.totalUp += 1
                        to.counted = True
                        time_now = datetime.datetime.now()
                        if (self.totalUp % 3 != 0):
                            self.write_record_to_DB(
                                time_now - datetime.timedelta(seconds=1), "in")
                    # if the direction is positive (indicating the object
                    # is moving down) AND the centroid is below the
                    # center line, count the object
                    elif direction > 0 and centroid[1] in range(
                            frameHeight // 2 - 30, frameHeight // 2 + 30):
                        self.totalDown += 1
                        to.counted = True
                        time_now = datetime.datetime.now()
                        if (self.totalDown % 3 != 0):
                            self.write_record_to_DB(
                                time_now + datetime.timedelta(seconds=1),
                                "out")
            # store the trackable object in our dictionary
            self.trackableObjects[objectID] = to
            # draw both the ID of the object and the centroid of the
            # object on the output frame
            #text = "ID {}".format(objectID)
            #cv.putText(frame, text, (centroid[0] - 10, centroid[1] - 10),
            #cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
            cv.circle(frame, (centroid[0], centroid[1]), 4, (0, 255, 0), -1)
        # construct a tuple of information we will be displaying on the
        # frame
        if self.totalU != self.totalUp:
            cv.line(frame, (0, frameHeight // 2),
                    (frameWidth, frameHeight // 2), (0, 255, 255), 2)
            cv.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 4)
            count_new = self.totalUp - self.totalU
            self.totalU = self.totalUp
            self.validate_up_count(cap, frame, count_new, time_now)
        if self.totalD != self.totalDown:
            cv.line(frame, (0, frameHeight // 2),
                    (frameWidth, frameHeight // 2), (0, 255, 255), 2)
            cv.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 4)
            count_new = self.totalDown - self.totalD
            self.totalD = self.totalDown
            self.validate_down_count(cap, frame, count_new, time_now)
        info = [
            ("Up", self.totalUp),
            ("Down", self.totalDown),
        ]
        #to write into file
        # f = open("outputfile.txt", "a")
        # timestamp = datetime.datetime.now().strftime("%Y%m%d_%H-%M-%S")
        # line = "{} , {}, {}\n".format(timestamp, totalUp, totalDown)
        # f.write(line)
        # f.close()

        # print(totalDown,totalUp)
        # loop over the info tuples and draw them on our frame
        for (i, (k, v)) in enumerate(info):
            text = "{}: {}".format(k, v)
            cv.putText(frame, text, (10, frameHeight - ((i * 20) + 20)),
                       cv.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)

    def write_record_to_DB(self, time_now, direction):
        names = [
            'Muskan Nehal', 'Sagar Shah', 'Karan Nayak', 'Naira Rohida',
            'Hemant Kulkarni', 'Rhea Haran', 'Sneha Rohra', 'Arjun Punjabi',
            'Ayu Talreja', 'Mohan Katyar'
        ]
        mycursor = mydb.cursor()
        insert_stmt = (
            "INSERT INTO identity_status(userName, floor, door, department,time, direction)"
            "VALUES (%s, %s, %s, %s, %s, %s)")
        data = (random.choice(names), self.floor, self.door, 'Stocks',
                time_now, direction)

        try:
            print("Video - ", self.name)
            mycursor.execute(insert_stmt, data)
            # Commit your changes in the database
            mydb.commit()
            print("[INFO] Inserted ", data)

        except Exception as e:
            # Rolling back in case of error
            mydb.rollback()
            print("Exception", e)

    def run(self):
        print(self.name + "  Starting " + str(datetime.datetime.now()))
        cv.namedWindow(self.name, 0)
        cv.resizeWindow(self.name, 700, 700)
        cvVideo = cv.VideoCapture(self.name)
        outputFile = str(self.name) + "_yolo_out_py.avi"
        vid_writer = cv.VideoWriter(
            outputFile, cv.VideoWriter_fourcc('M', 'J', 'P', 'G'), 30,
            (round(cvVideo.get(cv.CAP_PROP_FRAME_WIDTH)),
             round(cvVideo.get(cv.CAP_PROP_FRAME_HEIGHT))))

        while True:
            (isRead, cvImage) = self.attemptRead(cvVideo)
            if isRead == False:
                break
            # rgb = imutils.resize(cvVideo, width=750)
            #cv.resize(rgb, (300, 300))
            blob = cv.dnn.blobFromImage(cvImage,
                                        1 / 255, (inpWidth, inpHeight),
                                        [0, 0, 0],
                                        1,
                                        crop=False)
            self.net.setInput(blob)
            outs = self.net.forward(self.getOutputsNames())
            mydb = None
            self.postprocess(cvVideo, cvImage, outs)
            frameHeight = cvImage.shape[0]
            frameWidth = cvImage.shape[1]
            cv.line(cvImage, (0, frameHeight // 2),
                    (frameWidth, frameHeight // 2), (0, 255, 255), 2)
            cv.imshow(self.name, cvImage)
            vid_writer.write(cvImage)
            key = cv.waitKey(50)
            if key == 27:
                break

        cv.destroyWindow(self.name)
        print(self.name + "  Exiting " + str(datetime.datetime.now()))

    def validate_up_count(self, cap, current_frame, count, time_now):

        X = 2
        start_time = time_now - datetime.timedelta(seconds=X)
        end_time = time_now
        sql = "SELECT * FROM identity_status where floor=" + str(
            self.floor) + " and door=" + str(
                self.door) + " and direction='in' and time BETWEEN '" + str(
                    start_time) + "' AND '" + str(end_time) + "'"
        mycursor = mydb.cursor()
        mycursor.execute(sql)
        myresult = mycursor.fetchall()
        mycursor.close()
        mydb.commit()
        if len(myresult) != count:
            print("Video - ", self.name)
        print("[INFO] got " + str(len(myresult)) +
              " records when expected was " + str(count))
        if len(myresult) != count:
            fps = cap.get(cv.CAP_PROP_FPS)
            current_frame_number = cap.get(cv.CAP_PROP_POS_FRAMES)
            videotime = current_frame_number / fps
            print("[INFO] tailgating happened at  ", videotime)
            timestamp = time_now.strftime("%Y%m%d_%H-%M-%S")
            file_name = "G:\\Counting-People-master\\entry_floor_" + str(
                self.floor) + "time_" + str(timestamp) + ".jpg"
            if not cv.imwrite(file_name, current_frame):
                raise Exception("Could not write image")
            duration = 1000  # milliseconds
            freq = 440  # Hz
            winsound.Beep(freq, duration)
            time_diff = time_now - datetime.timedelta(seconds=5)
            sql = "Select distinct a.* from (Select b.* From (SELECT * FROM identity_status where floor=" + str(
                self.floor
            ) + " and door=" + str(self.door) + "  and time < '" + str(
                time_now
            ) + "' Order by time desc LIMIT 1 ) b UNION select * from identity_status where floor=" + str(
                self.floor) + " and door=" + str(
                    self.door
                ) + " and direction='in' and time between '" + str(
                    time_now) + "' and '" + str(time_diff) + "')a "
            mycursor = mydb.cursor()
            mycursor.execute(sql)
            myresult = mycursor.fetchall()
            mycursor.close()
            mydb.commit()
            table_body = ""
            for x in myresult:
                table_row = "<tr>\n" + "<td>" + x[1] + "</td>\n" + "<td>" + str(
                    x[2]) + "</td>\n" + "<td>" + str(
                        x[3]
                    ) + "</td>\n" + "<td>" + x[4] + "</td>\n" + "<td>" + str(
                        x[5]) + "</td>\n" + "<td>" + str(x[6]) + "</td>\n"
                table_body = table_body + table_row
            start_part = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8" />
                <style type="text/css">
                table {
                    background: white;
                    border-radius:3px;
                    border-collapse: collapse;
                    height: auto;
                    max-width: 900px;
                    padding:5px;
                    width: 100%;
                    animation: float 5s infinite;
                }
                th {
                    color:#D5DDE5;;
                    background:#1b1e24;
                    border-bottom: 4px solid #9ea7af;
                    font-size:14px;
                    font-weight: 300;
                    padding:10px;
                    text-align:center;
                    vertical-align:middle;
                }
                tr {
                    border-top: 1px solid #C1C3D1;
                    border-bottom: 1px solid #C1C3D1;
                    border-left: 1px solid #C1C3D1;
                    color:#666B85;
                    font-size:16px;
                    font-weight:normal;
                }
                tr:hover td {
                    background:#4E5066;
                    color:#FFFFFF;
                    border-top: 1px solid #22262e;
                }
                td {
                    background:#FFFFFF;
                    padding:10px;
                    text-align:left;
                    vertical-align:middle;
                    font-weight:300;
                    font-size:13px;
                    border-right: 1px solid #C1C3D1;
                }
                </style>
            </head>
            <body>
                You are recieving this email because system has observed tailgating <br>
                Please check the following details of person who entered exited before tailgating happened : <br>
                <table>
                <thead>
                    <tr style="border: 1px solid #1b1e24;">
                    <th>username</th>
                    <th>floor</th>
                    <th>door</th>
                    <th>department</th>
                    <th>timestamp</th>
                    <th>direction</th>
                    </tr>
                </thead>
                <tbody>
                """
            later_part = """
                </tbody>
                </table>
                Refer the snapshot at the time of tailgating...
                For more assistance please contact our support team:
                <a href='mailto:[email protected]'>[email protected]</a>.<br> 
                Thank you!
            </body>
            </html>
            """
            HTML = start_part + table_body + later_part
            thread = threading.Thread(target=self.send_Email(HTML, file_name))
            thread.start()
        print(
            "------------------------------------------------------------------------------------------------------------------------------------------------------------------"
        )

    def validate_down_count(self, cap, current_frame, count, time_now):

        seconds = 0
        while seconds != 3:
            current_time = time_now + datetime.timedelta(seconds=seconds)
            current_time = current_time.replace(microsecond=0)
            sql = "SELECT * FROM identity_status where floor=" + str(
                self.floor) + " and door=" + str(
                    self.door) + " and direction='out' and time LIKE '%" + str(
                        current_time) + "%'"
            mycursor = mydb.cursor()
            mycursor.execute(sql)
            myresult = mycursor.fetchall()
            seconds = seconds + 1
            mycursor.close()
            mydb.commit()
            if (len(myresult) != 0):
                break

        if len(myresult) != count:
            print("Video - ", self.name)
        print("[INFO] got " + str(len(myresult)) +
              " records when expected was " + str(count))
        if len(myresult) != count:
            fps = cap.get(cv.CAP_PROP_FPS)
            current_frame_number = (cap.get(cv.CAP_PROP_POS_FRAMES))
            videotime = current_frame_number / fps
            print("[INFO] tailgating happened at  ", videotime)
            timestamp = time_now.strftime("%Y%m%d_%H-%M-%S")
            file_name = "G:\\Counting-People-master\\exit_floor_" + str(
                self.floor) + "time_" + str(timestamp) + ".jpg"
            if not cv.imwrite(file_name, current_frame):
                raise Exception("Could not write image")
            duration = 1000  # milliseconds
            freq = 440  # Hz
            winsound.Beep(freq, duration)
            time_diff = time_now - datetime.timedelta(seconds=5)
            sql = "Select distinct a.* from (Select b.* From (SELECT * FROM identity_status where floor=" + str(
                self.floor
            ) + " and door=" + str(self.door) + "  and time < '" + str(
                time_now
            ) + "' Order by time desc LIMIT 1 ) b UNION select * from identity_status where floor=" + str(
                self.floor) + " and door=" + str(
                    self.door
                ) + " and direction='out' and time between '" + str(
                    time_now) + "' and '" + str(time_diff) + "')a "
            mycursor = mydb.cursor()
            mycursor.execute(sql)
            myresult = mycursor.fetchall()
            mycursor.close()
            mydb.commit()
            table_body = ""
            for x in myresult:
                table_row = "<tr>\n" + "<td>" + x[1] + "</td>\n" + "<td>" + str(
                    x[2]) + "</td>\n" + "<td>" + str(
                        x[3]
                    ) + "</td>\n" + "<td>" + x[4] + "</td>\n" + "<td>" + str(
                        x[5]) + "</td>\n" + "<td>" + str(x[6]) + "</td>\n"
                table_body = table_body + table_row
            start_part = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8" />
                <style type="text/css">
                table {
                    background: white;
                    border-radius:3px;
                    border-collapse: collapse;
                    height: auto;
                    max-width: 900px;
                    padding:5px;
                    width: 100%;
                    animation: float 5s infinite;
                }
                th {
                    color:#D5DDE5;;
                    background:#1b1e24;
                    border-bottom: 4px solid #9ea7af;
                    font-size:14px;
                    font-weight: 300;
                    padding:10px;
                    text-align:center;
                    vertical-align:middle;
                }
                tr {
                    border-top: 1px solid #C1C3D1;
                    border-bottom: 1px solid #C1C3D1;
                    border-left: 1px solid #C1C3D1;
                    color:#666B85;
                    font-size:16px;
                    font-weight:normal;
                }
                tr:hover td {
                    background:#4E5066;
                    color:#FFFFFF;
                    border-top: 1px solid #22262e;
                }
                td {
                    background:#FFFFFF;
                    padding:10px;
                    text-align:left;
                    vertical-align:middle;
                    font-weight:300;
                    font-size:13px;
                    border-right: 1px solid #C1C3D1;
                }
                </style>
            </head>
            <body>
                You are recieving this email because system has observed tailgating <br>
                Please check the following details of person who entered exited before tailgating happened : <br>
                <table>
                <thead>
                    <tr style="border: 1px solid #1b1e24;">
                    <th>username</th>
                    <th>floor</th>
                    <th>door</th>
                    <th>department</th>
                    <th>timestamp</th>
                    <th>direction</th>
                    </tr>
                </thead>
                <tbody>
                """
            later_part = """
                </tbody>
                </table>
                Refer the snapshot at the time of tailgating...
                For more assistance please contact our support team:
                <a href='mailto:[email protected]'>[email protected]</a>.<br> 
                Thank you!
            </body>
            </html>
            """

            HTML = start_part + table_body + later_part
            thread = threading.Thread(target=self.send_Email(HTML, file_name))
            thread.start()
        print(
            "------------------------------------------------------------------------------------------------------------------------------------------------------------------"
        )

    def send_Email(self, message, file_name):

        subject_template_name = 'Security Alert '
        img_data = open(file_name, 'rb').read()
        fromaddr = "*****@*****.**"
        toaddr = "*****@*****.**"
        mail = MIMEMultipart()
        mail['From'] = fromaddr
        mail['To'] = toaddr
        baseurl = "g:/counting-people-master"
        mail['Subject'] = subject_template_name
        mail.attach(MIMEText(message, 'html'))
        image = MIMEImage(img_data, name=os.path.basename(file_name))
        mail.attach(image)
        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.ehlo()
        server.starttls()
        server.ehlo()
        server.login(fromaddr, 'softcorner@2020')
        text = mail.as_string()
        server.sendmail(fromaddr, toaddr, text)
        server.quit()