Call Variable form another class

Hye Guys, I would like to ask a question regarding python. Basiclly I have two class Face and VideoCamera. In my class Face class I have one function call load_all(). In this function it has one variable call self.known_encoding_faces.

My question is how can i get the variable self.known_encoding_faces and this variable can be used by class of VIdeoCamera

Face Class

import face_recognition
from os import path
import cv2



class Face:
    def __init__(self, app):
        self.train_img = app.config["train_img"]
        self.db = app.db
        self.faces = []
        self.face_user_keys = {}
        self.known_encoding_faces = []  # faces data for recognition
        self.load_all()


    def load_user_by_index_key(self, index_key=0):

        key_str = str(index_key)

        if key_str in self.face_user_keys:
            return self.face_user_keys[key_str]

        return None

    def load_train_file_by_name(self,name):
        trained_train_img = path.join(self.train_img, 'trained')
        return path.join(trained_train_img, name)

    def load_unknown_file_by_name(self,name):
        unknown_img = path.join(self.train_img, 'unknown')
        return path.join(unknown_img, name)


    def load_all(self):
        results = self.db.select('SELECT faces.id, faces.user_id, faces.filename, faces.created FROM faces')
        for row in results:

            user_id = row[1]
            filename = row[2]

            face = {
                "id": row[0],
                "user_id": user_id,
                "filename": filename,
                "created": row[3]
            }

            self.faces.append(face)

            face_image = face_recognition.load_image_file(self.load_train_file_by_name(filename))
            face_image_encoding = face_recognition.face_encodings(face_image)[0]
            index_key = len(self.known_encoding_faces)
            self.known_encoding_faces.append(face_image_encoding)
            index_key_string = str(index_key)
            self.face_user_keys['{0}'.format(index_key_string)] = user_id

Camera Class

import face_recognition
from os import path
import cv2
from db import Database
from face import Face

#Face.self.known_encoding_faces

class VideoCamera(object):
    def __init__(self):
        # Using OpenCV to capture from device 0. If you have trouble capturing
        # from a webcam, comment the line below out and use a video file
        # instead.
        self.video_capture = cv2.VideoCapture(0)
        self.face_locations = []
        self.face_encodings = []
        self.face_names = []
        self.process_this_frame = True
        # If you decide to use video.mp4, you must have this file in the folder
        # as the main.py.
        # self.video = cv2.VideoCapture('video.mp4')

    def __del__(self):
        self.video_capture.release()

    def get_frame(self):
        success, frame = self.video_capture.read()
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
        rgb_small_frame = small_frame[:, :, ::-1]
        if self.process_this_frame:
            face_locations = face_recognition.face_locations(rgb_small_frame)
            face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
            print(face_encodings)
        ret, jpeg = cv2.imencode('.jpg', frame)
        return jpeg.tobytes()

Hope someone can help me on this matter. I have try for two days. :frowning:

Without knowing use case, it’s a little difficult to say. But here’s a fairly easy way to approach it. The list self.known_face_encodings is an attribute of the class Face, not a variable of the function load_all(). So after class instantiation, the attribute can be directly referenced from the class instance.
Ex:

>>> face_instance = Face(app_instance)
>>> print(face_instance.known_encoding_faces)
[]  # Prints an empty list because it hasn't peen populated yet

You can feed it to the instance of VideoCamera on initialization or later as an attribute/function argument.

# Modify the VideoCamera Class to accept this argument on init
>>> camera_instance = VideoCamera(face_instance.known_encoding_faces)
or
# Use it as a function argument
>>> camera_instance = VideoCamera()
>>> camera_instance.some_function(face_instance.known_encoding_faces)

Hopefully this helps.

Hye @kylec Thank for reply. I will this approach first. Btw do you need full source code so that u can understand the use case? I have try this for two days but it’s still not working

@kylec I try to write this code in my camera but it’s not working.

>>> face_instance = Face(app_instance)
>>> print(face_instance.known_encoding_faces)
[]  # Prints an empty list because it hasn't peen populated ye

show error like this

NameError: name 'app_instance' is not defined```

So app_instance was just an example I used because the way your code is set up for the class Face, it needs an app argument on instantiation. The line def __init__(self, app):

To get your code to work, you need to replace app_instance with whatever app object you were planning on using there.

I keep trying but keep fail. :frowning: really confusing me. I will share my code to you… hope u can help if u have time.

app.py

from flask import request
from os import path, getcwd
import time
from face import Face
import cv2
from camera import VideoCamera


app.config['file_allowed'] = ['image/png', 'image/jpeg']
app.config['train_img'] = path.join(getcwd(), 'train_img')
app.db = Database()
app.face = Face(app)
#app.face = VideoCamera(app)
#print (app.face)
#app.camera = VideoCamera(app)

def gen(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

@app.route('/video_feed')
def video_feed():
    return Response(gen(VideoCamera()),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/')
def index():
    return render_template('index.html')

def success_handle(output, status=200, mimetype='application/json'):
    return Response(output, status=status, mimetype=mimetype)


def error_handle(error_message, status=500, mimetype='application/json'):
    return Response(json.dumps({"error": {"message": error_message}}), status=status, mimetype=mimetype)

def get_user_by_id(user_id):
    user = {}
    results = app.db.select(
        'SELECT users.id, users.name, users.created, faces.id, faces.user_id, faces.filename,faces.created FROM users LEFT JOIN faces ON faces.user_id = users.id WHERE users.id = ?',
        [user_id])
    index = 0
    for row in results:
        print(row)
        face = {
            "id": row[3],
            "user_id": row[4],
            "filename": row[5],
            "created" : row[6],
        }
        if index == 0:
            user = {
                "id": row[0],
                "name": row[1],
                "created": row[2],
                "faces" : [],
            }
        if 3 in row:
            user["faces"].append(face)
        index = index + 1
    if 'id' in user:
        return user
    return None

face.py file

import face_recognition
from os import path
import cv2



class Face:
    def __init__(self, app):
        self.train_img = app.config["train_img"]
        self.db = app.db
        self.faces = []
        self.face_user_keys = {}
        self.known_encoding_faces = []  # faces data for recognition
        self.load_all()
        self.get_data()





    def load_user_by_index_key(self, index_key=0):

        key_str = str(index_key)

        if key_str in self.face_user_keys:
            return self.face_user_keys[key_str]

        return None

    def load_train_file_by_name(self,name):
        trained_train_img = path.join(self.train_img, 'trained')
        return path.join(trained_train_img, name)

    def load_unknown_file_by_name(self,name):
        unknown_img = path.join(self.train_img, 'unknown')
        return path.join(unknown_img, name)


    def load_all(self):
        results = self.db.select('SELECT faces.id, faces.user_id, faces.filename, faces.created FROM faces')
        for row in results:

            user_id = row[1]
            filename = row[2]

            face = {
                "id": row[0],
                "user_id": user_id,
                "filename": filename,
                "created": row[3]
            }

            self.faces.append(face)

            face_image = face_recognition.load_image_file(self.load_train_file_by_name(filename))
            face_image_encoding = face_recognition.face_encodings(face_image)[0]
            index_key = len(self.known_encoding_faces)
            self.known_encoding_faces.append(face_image_encoding)
            index_key_string = str(index_key)
            self.face_user_keys['{0}'.format(index_key_string)] = user_id

    def get_data(self):
        return self.known_encoding_faces

    def recognize(self,unknown_filename):
        unknown_image = face_recognition.load_image_file(self.load_unknown_file_by_name(unknown_filename))
        unknown_encoding_image =  face_recognition.face_encodings(unknown_image)[0]

        results = face_recognition.compare_faces(self.known_encoding_faces, unknown_encoding_image);

        print("results", results)

        index_key = 0
        for matched in results:

            if matched:
                # so we found this user with index key and find him
                user_id = self.load_user_by_index_key(index_key)

                return user_id

            index_key = index_key + 1
        return None

Camera.py

from flask import Flask, Response, json, render_template
from werkzeug.utils import secure_filename
from flask import request
from os import path, getcwd
import time
from face import Face
from db import Database
cam = Flask(__name__)
import cv2
import face_recognition

#Face.self.known_encoding_faces
# cam.config['file_allowed'] = ['image/png', 'image/jpeg']
# cam.config['train_img'] = path.join(getcwd(), 'train_img')
# cam.db = Database()


# face_instance = Face(cam)
# test = face_instance.known_encoding_faces
# print(test)


class VideoCamera(object):


    def __init__(self):
        # Using OpenCV to capture from device 0. If you have trouble capturing
        # from a webcam, comment the line below out and use a video file
        # instead.
        self.faces = []
        self.face_locations = []
        self.face_encodings = []
        self.face_names = []
        self.process_this_frame = True
        self.video_capture = cv2.VideoCapture(0)
        self.load_data()
        print(self.data)
        # If you decide to use video.mp4, you must have this file in the folder
        # as the main.py.
        # self.video = cv2.VideoCapture('video.mp4')

    # def load_train_file_by_name(self,name):
    #     trained_train_img = path.join(cam.config['train_img'], 'trained')
    #     return path.join(trained_train_img, name)

    # def load_unknown_file_by_name(self,name):
    #     unknown_img = path.join(cam.config['train_img'], 'unknown')
    #     return path.join(unknown_img, name)


    # def load_data(self):
    #     results = cam.db.select('SELECT faces.id, faces.user_id, faces.filename, faces.created FROM faces')
    #     for row in results:


    #         user_id = row[1]
    #         filename = row[2]

    #         face = {
    #              "id": row[0],
    #              "user_id": user_id,
    #              "filename": filename,
    #              "created": row[3]
    #          }

    #         self.faces.append(face)

    #         face_image = face_recognition.load_image_file(self.load_train_file_by_name(filename))
    #         face_image_encoding = face_recognition.face_encodings(face_image)[0]
    #         index_key = len(self.known_encoding_faces)
    #         self.known_encoding_faces.append(face_image_encoding)
    #         print(self.known_encoding_faces)
            #index_key_string = str(index_key)
            #self.face_user_keys['{0}'.format(index_key_string)] = user_id



    def __del__(self):
        self.video_capture.release()

    def get_frame(self):
        success, frame = self.video_capture.read()
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
        rgb_small_frame = small_frame[:, :, ::-1]
        if self.process_this_frame:
        # Find all the faces and face encodings in the current frame of video
            face_locations = face_recognition.face_locations(rgb_small_frame)
            face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

            face_names = []
            for face_encoding in face_encodings:
                # See if the face is a match for the known face(s)
                matches = face_recognition.compare_faces(self.known_encoding_faces, face_encoding)
                name = "Unknown"

                if True in matches:
                    first_match_index = matches.index(True)
                    #name = known_face_names[first_match_index]

                face_names.append(name)

        self.process_this_frame = not self.process_this_frame
        # Display the results

                # Grab a single frame of video
                # We are using Motion JPEG, but OpenCV defaults to capture raw images,
                # so we must encode it into JPEG in order to correctly display the
                # video stream.
        ret, jpeg = cv2.imencode('.jpg', frame)
        return jpeg.tobytes()

This my code for these 3 file…hope you can help me if u have time

Well lets start with this, What exactly isn’t working with your app?

As some general notes from reading through this:

  • Look over your imports for each script. It might just be my imagination, but it looks like they aren’t matching what you need in each script.
  • In app.py, you appear to be working with an app object (app.config, app.db, app.face), but I don’t see where this object was ever created or imported into the script.
    • Don’t you need something like app = Flask(__name__) first? (This would be the app_instance I was referring to earlier)
    • In Camera.py you create a Flask App on line 8: cam = Flask(__name__). Why?

Hye Kylec, Thank You for replying again. Really appreciate your effort to help me. Let’s me explain to you. I try to create mini project for face recognition system. In order to develop that I have follow this tutorial while understanding the code this tutorial have been used.

Currently I want to develop real time face recognition by using my webcam by using a flask. So in order to achieve this, I plan to use known_face_encoding variable in face.py in camera.py. The reason I want to use this known_face_encoding variable is to compare with the face data captured in my webcam. So my problem coming when i try to pass the known_face_encoding variable to my camera.py file.

My expected result is when i run my app.py I and open my webcam in set path the command prompt will show the printed known_face_encoding variable. I believe if this work means this known_face_encoding variable successfully can be used by camera.py file.

Just ignore the cam = Flask(name). I forget to delete it. Actually my plan is if i don’t able to get the known_face_encoding variable I will repeat created back all the function I have been created in my face.py and app.py means i will get the data back and train the data again.

i will share all my original code to here.

app.py

from flask import Flask, Response, json, render_template
from werkzeug.utils import secure_filename
from flask import request
from os import path, getcwd
import time
from face import Face
from db import Database
app = Flask(__name__)
import cv2
from camera import VideoCamera


app.config['file_allowed'] = ['image/png', 'image/jpeg']
app.config['train_img'] = path.join(getcwd(), 'train_img')
app.db = Database()
app.face = Face(app)
#print (app.face)
#app.camera = VideoCamera(app)

def gen(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

@app.route('/video_feed')
def video_feed():
    return Response(gen(VideoCamera()),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/')
def index():
    return render_template('index.html')

def success_handle(output, status=200, mimetype='application/json'):
    return Response(output, status=status, mimetype=mimetype)


def error_handle(error_message, status=500, mimetype='application/json'):
    return Response(json.dumps({"error": {"message": error_message}}), status=status, mimetype=mimetype)

def get_user_by_id(user_id):
    user = {}
    results = app.db.select(
        'SELECT users.id, users.name, users.created, faces.id, faces.user_id, faces.filename,faces.created FROM users LEFT JOIN faces ON faces.user_id = users.id WHERE users.id = ?',
        [user_id])
    index = 0
    for row in results:
        print(row)
        face = {
            "id": row[3],
            "user_id": row[4],
            "filename": row[5],
            "created" : row[6],
        }
        if index == 0:
            user = {
                "id": row[0],
                "name": row[1],
                "created": row[2],
                "faces" : [],
            }
        if 3 in row:
            user["faces"].append(face)
        index = index + 1
    if 'id' in user:
        return user
    return None

def delete_user_by_id(user_id):
    app.db.delete('DELETE FROM users WHERE users.id = ?', [user_id])
    # also delete all faces with user id
    app.db.delete('DELETE FROM faces WHERE faces.user_id = ?', [user_id])

#@app.route("/")
#def hello():
#    return "Welcome to machine learning model APIs!"


@app.route('/api/train',methods=['POST'])
def train():
    output=json.dumps({"success": True})

    if 'file' not in request.files:
        print("Face Image Is Required")
        return error_handle("face Image is required")
    else:
        print("File Request", request.files)
        file = request.files['file']
        if file.mimetype not in app.config['file_allowed']:
            print("file extension is not allowed")
            error_handle("we are only allow upload file with .png , *.jpg")
        else:
            name = request.form['name']
            print("information of that face", name)
            print("File is allowed and will be saved in ", app.config['train_img'])
            filename = secure_filename(file.filename)
            print(filename)
            training_image = path.join(app.config['train_img'], 'trained')
            print(training_image)
            file.save(path.join(training_image, filename))

            # # save to our sqlite database.db
            created = int(time.time())
            user_id = app.db.insert('INSERT INTO users (name,created) values(?,?)', [name,created])
            if user_id:
                print("user data already save", name, user_id)
                face_id = app.db.insert('INSERT INTO faces (user_id,filename,created) values (?,?,?)', [user_id, filename, created])
                print(face_id)
                if face_id:
                    print("cool face has been saved")
                    face_data = {"id": face_id, "filename": filename, "created": created}
                    print(face_data)
                    return_output = json.dumps({"id": user_id, "name": name, "face": [face_data]})
                    return success_handle(return_output)
                else:
                    print("an error saving image")
                    return error_handle("an error saving image")
            else:
                print("Something happen")
                return error_handle("An error inserting new user")
        print("Request Is Contain Image")

    return success_handle(output)

# route for user profile
@app.route('/api/users/<int:user_id>', methods=['GET', 'DELETE'])
def user_profile(user_id):
    if request.method == 'GET':
        user = get_user_by_id(user_id)
        if user:
            return success_handle(json.dumps(user),200)
        else:
            return error_handle("user not found",404)

    if request.method == 'DELETE':
        delete_user_by_id(user_id)
        return success_handle(json.dumps({"deleted":True}))
    
@app.route('/api/recognize', methods=['POST'])
def recognize():
    if 'file' not in request.files:
        return error_handle("Image is required")
    else:
        file = request.files['file']
        #file extension validation
        if file.mimetype not in app.config['file_allowed']:
            return error_handle("File extension is not allowed")
        else:

            filename = secure_filename(file.filename)
            unknown_storage = path.join(app.config["train_img"], 'unknown')
            file_path = path.join(unknown_storage, filename)
            file.save(file_path)

            user_id = app.face.recognize(filename)
            print(user_id)
            if user_id:
                user = get_user_by_id(user_id)
                message = {"message": "Hey we found {0} matched with your face image".format(user["name"]),"user": user}
                return success_handle(json.dumps(message))
            else:

                return error_handle("Sorry we can not found any people matched with your face image, try another image")


    return success_handle(json.dumps({"filename to compare is": filename}))


app.run()

Face.py

import face_recognition
from os import path
import cv2



class Face:
    def __init__(self, app):
        self.train_img = app.config["train_img"]
        self.db = app.db
        self.faces = []
        self.face_user_keys = {}
        self.known_encoding_faces = []  # faces data for recognition
        self.load_all()
        self.get_data()

    def load_user_by_index_key(self, index_key=0):

        key_str = str(index_key)

        if key_str in self.face_user_keys:
            return self.face_user_keys[key_str]

        return None

    def load_train_file_by_name(self,name):
        trained_train_img = path.join(self.train_img, 'trained')
        return path.join(trained_train_img, name)

    def load_unknown_file_by_name(self,name):
        unknown_img = path.join(self.train_img, 'unknown')
        return path.join(unknown_img, name)




    def load_all(self):
        results = self.db.select('SELECT faces.id, faces.user_id, faces.filename, faces.created FROM faces')
        for row in results:

            user_id = row[1]
            filename = row[2]

            face = {
                "id": row[0],
                "user_id": user_id,
                "filename": filename,
                "created": row[3]
            }

            self.faces.append(face)

            face_image = face_recognition.load_image_file(self.load_train_file_by_name(filename))
            face_image_encoding = face_recognition.face_encodings(face_image)[0]
            index_key = len(self.known_encoding_faces)
            self.known_encoding_faces.append(face_image_encoding)
            index_key_string = str(index_key)
            self.face_user_keys['{0}'.format(index_key_string)] = user_id
            
    def get_data(self):
        self.data = self.known_encoding_faces
        return self.data
    


    
    
    def recognize(self,unknown_filename):
        unknown_image = face_recognition.load_image_file(self.load_unknown_file_by_name(unknown_filename))
        unknown_encoding_image =  face_recognition.face_encodings(unknown_image)[0]

        results = face_recognition.compare_faces(self.known_encoding_faces, unknown_encoding_image);

        print("results", results)

        index_key = 0
        for matched in results:

            if matched:
                # so we found this user with index key and find him
                user_id = self.load_user_by_index_key(index_key)

                return user_id

            index_key = index_key + 1
        return None

db.py

import sqlite3
from os import path, getcwd

db = path.join(getcwd(), 'database.db')

class Database:
    def __init__(self):
        self.connection = sqlite3.connect('database.db', check_same_thread=False)
    def query(self, q, arg=()):
        cursor = self.connect.cursor()
        cursor.execuated(q,arg)
        results = cursor.fetchall()
        cursor.close()

        return result

    def insert(self,q,arg=()):
        cursor = self.connection.cursor()
        cursor.execute(q,arg) 
        self.connection.commit()
        return cursor.lastrowid
        cursor.close
        return result 

    def select(self, q, arg=()):
        cursor = self.connection.cursor()
        return cursor.execute(q, arg)

    def delete(self, q, arg=()):
        cursor = self.connection.cursor()
        result = cursor.execute(q, arg)
        self.connection.commit()
        return result

camera.py

import face_recognition
from os import path
import cv2
from face import Face



class VideoCamera(object):
    def __init__(self):
        # Using OpenCV to capture from device 0. If you have trouble capturing
        # from a webcam, comment the line below out and use a video file
        # instead.
        self.video_capture = cv2.VideoCapture(0)

       
        # If you decide to use video.mp4, you must have this file in the folder
        # as the main.py.
        # self.video = cv2.VideoCapture('video.mp4')

    def __del__(self):
        self.video_capture.release()

    def get_frame(self):
        success, frame = self.video_capture.read()
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
        rgb_small_frame = small_frame[:, :, ::-1]
        # Grab a single frame of video
        # We are using Motion JPEG, but OpenCV defaults to capture raw images,
        # so we must encode it into JPEG in order to correctly display the
        # video stream.
        ret, jpeg = cv2.imencode('.jpg', frame)
        return jpeg.tobytes()

            ```

Ok, I’m catching on I think. I have a question about your /video_feed route though. You send a response which (I’m presuming) is the binary string representation of a photo (webcam frame grab) back to the client. How exactly do you interact with the client’s webcam? The cv2.VideoCapture(0) initialization of class VideoCamera is going to attempt to read a video feed running on the back end, not the front end, right?