6
\$\begingroup\$

I have been using the following script for face recognition as a security feature:

main.py

from itertools import izip
from PIL import Image
def compare(self,pic): 
    i1 = Image.open("pic1.jpg")
    i2 = Image.open(pic)
    size = i1.size
    i2 = i2.resize(size)
    assert i1.mode == i2.mode, "Different kinds of images."
    assert i1.size == i2.size, "Different sizes."

    pairs = izip(i1.getdata(), i2.getdata())
    if len(i1.getbands()) == 1:
        # for gray-scale jpegs
        dif = sum(abs(p1-p2) for p1,p2 in pairs)
    else:
        dif = sum(abs(c1-c2) for p1,p2 in pairs for c1,c2 in zip(p1,p2))
    ncomponents = i1.size[0] * i1.size[1] * 3
    print ((dif / 255.0 * 100) / ncomponents)
    return (dif / 255.0 * 100) / ncomponents

def password(self):
    import passw
    y=str(self.password_input.text)
    x=passw.verify(y)
    if x == True:
        try:
            os.startfile("recog.py")
            import time
            time.sleep(6)
            x = self.compare("security.jpg")
            if x <= 30:
                os.remove("pic1.jpg")
                os.rename("security.jpg","pic1.jpg")
                return True
            else:
                raise ValueError
        except ValueError, e:
            print(e)
            sf=open('secure.txt','w')
            sf.write("")
            sf.close()
            if os.path.exists("securitylog.jpg"):
                from datetime import datetime, date, time
                dt = datetime.today()
                t=dt.strftime("%A, %d. %B %Y %H:%M %p")
                t='{0:%H:%M }'.format(dt)
                f='{0:%A}, {0:%d} of {0:%B}, {0:%Y}.'.format(dt)
                timed=(("Date: ",f,"\nTime: ",t))
                timed=''.join(timed)
                sf=open('secure.txt','a')
                sf.write(timed)
                sf.close()
                kl=Thread(target=self.say, args="You are not authorized to access this program.")
                kl.start()
                p = Wrong()
                p.open()
            else:
                os.rename("security.jpg","securitylog.jpg")

    else:
        sf=open('secure.txt','w')
        sf.write("")
        sf.close()
        if os.path.exists("securitylog.jpg"):
            from datetime import datetime, date, time
            dt = datetime.today()
            t=dt.strftime("%A, %d. %B %Y %H:%M %p")
            t='{0:%H:%M }'.format(dt)
            f='{0:%A}, {0:%d} of {0:%B}, {0:%Y}.'.format(dt)
            timed=(("Date: ",f,"\nTime: ",t))
            timed=''.join(timed)
            sf=open('secure.txt','a')
            sf.write(timed)
            sf.close()
            kl=Thread(target=self.say, args="You are not authorized to access this program.")
            kl.start()
            p = Wrong()
            p.open()
        else:
            os.rename("security.jpg","securitylog.jpg")

passw.py:

from passlib.hash import sha256_crypt
import onetimepad
def verify(string):
        y=string
        key=y[-2:]
        enc=onetimepad.encrypt(y,key)
        x=sha256_crypt.verify(enc,'<hash>')
        return x
def main():
        x=raw_input("Enter Password: ")
        print verify(x)

if __name__ =="__main__":
        main()

recog.py

#!/usr/bin/env python
# Python 2/3 compatibility
from __future__ import print_function
import sys
import numpy as np
import cv2
# local modules
from video import create_capture
from common import clock, draw_str


def detect(img, cascade):
    rects = cascade.detectMultiScale(img, scaleFactor=1.3, minNeighbors=4, minSize=(30, 30),
                                     flags=cv2.CASCADE_SCALE_IMAGE)
    if len(rects) == 0:
        return []
    rects[:,2:] += rects[:,:2]
    return rects

def draw_rects(img, rects, color):
    for x1, y1, x2, y2 in rects:
        cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)

if __name__ == '__main__':
    import sys, getopt
    print("Face Recognition using Haar Cascades")

    args, video_src = getopt.getopt(sys.argv[1:], '', ['cascade=', 'nested-cascade='])
    try:
        video_src = video_src[0]
    except:
        video_src = 0
    args = dict(args)
    cascade_fn = args.get('--cascade', "E:\\Python27\\My programs\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml")
    nested_fn  = args.get('--nested-cascade', "E:\\Python27\\My programs\\opencv\\sources\\data\\haarcascades\\haarcascade_eye.xml")

    cascade = cv2.CascadeClassifier(cascade_fn)
    nested = cv2.CascadeClassifier(nested_fn)

    cam = create_capture(video_src, fallback='synth:bg=../data/lena.jpg:noise=0.05')

    while True:
        ret, img = cam.read()
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        gray = cv2.equalizeHist(gray)

        t = clock()
        rects = detect(gray, cascade)
        vis = img.copy()
        draw_rects(vis, rects, (0, 255, 0))
        if not nested.empty():
            for x1, y1, x2, y2 in rects:
                roi = gray[y1:y2, x1:x2]
                vis_roi = vis[y1:y2, x1:x2]
                subrects = detect(roi.copy(), nested)
                print("Face detected")
                image = vis_roi
                cv2.imwrite('security.jpg', image)
                cv2.destroyWindow('facedetect')
                sys.exit()
        dt = clock() - t

        draw_str(vis, (20, 20), 'time: %.1f ms' % (dt*1000))
        cv2.imshow('facedetect', vis)

        if 0xFF & cv2.waitKey(5) == 27:
            break
    cv2.destroyAllWindows()

As you can see i have provide all the code to ensure that my face recognition program works.

I feel that the above code is not very efficient. Is there a better way to use face recognition as a security measure using python?

\$\endgroup\$
  • \$\begingroup\$ Hi, asked question about your question here, you might be interested :) \$\endgroup\$ – MatthewRock Sep 6 '16 at 15:20
  • \$\begingroup\$ Please also read up on Intel 3D secure and Windows Hello, which enables this for the web, and Windows 10 devices. security.stackexchange.com/q/136161/396 \$\endgroup\$ – goodguys_activate Sep 8 '16 at 2:45
  • \$\begingroup\$ @MatthewRock I know that I'm replying really late, but that is in fact an amazing question. Personally, I still feel that it is a vaild security feature. Now that even Apple has FaceID, I guess my point still holds good \$\endgroup\$ – Vin Mar 25 '18 at 16:26
10
\$\begingroup\$

You should read and follow PEP8. This means:

  • Put all imports at the top of the file.
  • Put a space around assignment operators.
  • Place a space after most commas.
  • Use descriptive names.

This is as it makes your code much easier to read. We put spaces around words in English to increase readability, we do it in programming languages to do the same.


You should:

  • Use with.
    This makes sure the file is closed, even if the program errors. Say the user force quits the program, KeyboardInterrupt.

  • Don't use assert.
    assert is for debugging, not for live code. If I run your code with the -O flag, it removes all of these, and then your code is broken.

  • Allow more customizability.
    Passing to functions a couple of file names is not hard. What's more hard is when you decide to change pic1.jpg to image.jpg and also use pic1.jpeg. This means you'll need to re-write your code to allow you to do this.

  • Don't have massive try blocks.
    This can lead to masking of bugs. This is as you may have two functions that raise say ValueErrors. But you don't know which one raised ValueError, and now you're handling unknown states.

  • Again put all imports at the top of you files.
    This allows me to know what you are importing as soon as I open your file. This prevents confusion, like you did in main.py where you never import os, but you're using it.

  • Remove duplicated code.
    You need to put duplicated code in a new function or re-arrange your current one to be able to merge the duplicated code. Take password in main.py, you duplicated a large chunk of the function where you can join it together, or at least make a function for it.

The biggest changes I know how to make are to main.py. Other than the above, I changed your code to use less variables, and removed dead code. Take:

dt = datetime.today()
t=dt.strftime("%A, %d. %B %Y %H:%M %p")
t='{0:%H:%M }'.format(dt)
f='{0:%A}, {0:%d} of {0:%B}, {0:%Y}.'.format(dt)
timed=(("Date: ",f,"\nTime: ",t))
timed=''.join(timed)

The first t is dead code, you instantly overwrite t to something else, so you can remove it. After this you have the two timed variables, you can change this to a single str.format, Date: {}\nTime: {}. From this you should notice you can merge all the str.formats into one, and end up with:

timed = 'Date: {0:%A}, {0:%d} of {0:%B}, {0:%Y}.\nTime: {0:%H:%M }'.format(datetime.today())

I'll only show the changes to main.py, as the other files didn't have as much to change:

from itertools import izip
import time
from datetime import datetime, date, time

from PIL import Image

import passw


def compare(self, picture1, picture2): 
    image1 = Image.open(picture1)
    image2 = Image.open(picture2).resize(image1.size)
    if image1.mode != image2.mode:
        raise ValueError("Different kinds of images.")
    if image1.size != image2.size:
        raise ValueError("Different sizes.")

    pairs = izip(image1.getdata(), image2.getdata())
    if len(image1.getbands()) == 1:
        dif = sum(abs(p1-p2) for p1, p2 in pairs)
    else:
        dif = sum(abs(c1-c2) for p1, p2 in pairs for c1, c2 in zip(p1,p2))

    ret = (dif / 255.0 * 100) / image1.size[0] * image1.size[1] * 3
    print ret
    return ret


def password(self):
    y = str(self.password_input.text)
    x = passw.verify(y)
    if x:
        try:
            os.startfile("recog.py")
            time.sleep(6)
            if self.compare("pic1.jpg", "security.jpg") <= 30:
                os.remove("pic1.jpg")
                os.rename("security.jpg", "pic1.jpg")
                return True
            else:
                raise ValueError
        except ValueError, e:
            print(e)

    # If not x or ValueError.
    with open('secure.txt', 'w') as sf:
        sf.write('')
    if os.path.exists("securitylog.jpg"):
        with open('secure.txt', 'a') as sf:
            sf.write('Date: {0:%A}, {0:%d} of {0:%B}, {0:%Y}.\nTime: {0:%H:%M }'
                     .format(datetime.today()))
        kl = Thread(target=self.say, args="You are not authorized to access this program.")
        kl.start()
        p = Wrong()
        p.open()
    else:
        os.rename("security.jpg", "securitylog.jpg")
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.