How to capture id size photo with webcam using python

153 Views Asked by At

I have this few lines code which capture images using webcam but the pictures width and heigth is large.Is it a way i can have the frame to be small to capture images as the size of passport picture.

Is the any available resource I can use to achieve that .This is how I want my frame to look like so I can use the webcam to capture the images from the head to shoulders.

Image in web Final result should look like this

Example image is attached

import cv2

key = cv2.waitKey(1)
webcam = cv2.VideoCapture(0)
while True:
    try:
        check, frame = webcam.read()
        print(check)  # prints true as long as the webcam is running
        print(frame)  # prints matrix values of each framecd
        cv2.imshow("Capturing", frame)
        key = cv2.waitKey(1)
        if key == ord('s'):
            cv2.imwrite(filename='saved_img.jpg', img=frame)
            webcam.release()
            img_new = cv2.imread('saved_img.jpg', cv2.IMREAD_UNCHANGED)
            img_new = cv2.imshow("Captured Image", img_new) # SHOWS THE IMAGE AFTER CAPTURING
            cv2.waitKey(1650)
            cv2.destroyAllWindows()
            print("captured images saved")

            break
        elif key == ord('q'):
            print("Turning off camera.")
            webcam.release()
            print("Camera off.")
            print("Program ended.")
            cv2.destroyAllWindows()
            break

    except(KeyboardInterrupt):
        print("Turning off camera.")
        webcam.release()
        print("Camera off.")
        print("Program ended.")
        cv2.destroyAllWindows()
        break
2

There are 2 best solutions below

1
fmw42 On BEST ANSWER

Here is how to crop to 2in x 2in using Python/PIL. We need to use PIL in order to set the density. I do not believe that OpenCV allows that. I assume that you want to crop in the center. If not, and for example from the top, let me know. But that will likely crop off the chin.

Unless you have an interactive system that allows a crop location/size specification, you cannot account for every picture, i.e., how big the person will be in the frame. So you also may not know where the head is.

Input (assumed fixed 480x640 portrait mode size):

enter image description here

import numpy as np
from PIL import Image

# read the input
# https://photogov.com/documents/bs-passport-480x640-photo/
img = Image.open('portrait.jpg')

# get dimensions (assume 480x640)
width, height = img.size

# for 2in x 2in printed result, we want to crop an aspect ratio of 1:1 in center
# so since the height will be larger than the width, we use the width for both dimensions
w2 = xcent = width//2
h2 = ycent = height//2
top = ycent - w2
left = xcent - w2
bottom = ycent + w2
right = xcent + w2

# crop input
crop = img.crop((left, top, right, bottom))

# get crop size
wd, ht = crop.size

# save image with density appropriate for 2in x 2in print
xprint = 2
yprint = 2
xdensity = wd//xprint
ydensity = ht//yprint
crop.save('portrait_2in_x_2in.jpg', dpi=(xdensity, ydensity))

# show cropped Image
crop.show()

Cropped Result:

enter image description here

2
fmw42 On

Here is the equivalent code for the case of 3.5cm x 4.5cm print output in Python/PIL

Input:

enter image description here

import numpy as np
from PIL import Image
import os

# read the input
# https://photogov.com/documents/bs-passport-480x640-photo/
img = Image.open('portrait.jpg')

# get dimensions (assume 480x640)
width, height = img.size

# compute input height/width ratio, which is 640/480 = 1.3333
in_ratio = height/width

# for 3.5 cm x 4.5 cm printed result, we want to crop an aspect ratio of 3.5:4.5 in center,
# which is a height/width ratio of 4.5/3.5 = 1.2857
out_ratio = 4.5/3.5

# test if in ratio is larger than out ratio
if in_ratio > out_ratio:
    # so if the input aspect ratio is larger than the output ratio, 
    # we use the width of the input as the output and compute the height
    # from the aspect ratios
    w2 = xcent = width//2
    h2 = ycent = height//2
    top = ycent - h2*out_ratio/in_ratio
    left = xcent - w2
    bottom = ycent + h2*out_ratio/in_ratio
    right = xcent + w2
else:
    print("Error: input aspect ratio is not larger than output aspect ratio")
    print("Aborting")
    os.abort()

# crop input
crop = img.crop((left, top, right, bottom))

# get crop size
wd, ht = crop.size

# save image with density appropriate for 3.5 cm x 4.5 cm print
# convert sizes to inches
xprint = 3.5/2.54
yprint = 4.5/2.54
xdensity = wd//xprint
ydensity = ht//yprint
crop.save('portrait_3p5cm_x_3p5cm.jpg', dpi=(xdensity, ydensity))

# show cropped Image
crop.show()

Cropped Result:

enter image description here