Friends, I need to implement a code, which blur faces from given images (I am not a dev so this is really difficult to me). I found out that I can use OpenCV and cvlib to do that and found a sample code (repository from cvlib) which does part of the job.
I understood that I need to get the subfaces and apply the face blur to them and I could do it but now I don't know how to add the blurred face to original image. Could someone help me with that?
import cvlib as cv
import sys
from cv2 import cv2
import os
# read input image
image = cv2.imread('path')
# apply face detection
faces, confidences = cv.detect_face(image)
print(faces)
print(confidences)
# loop through detected faces
for face,conf in zip(faces,confidences):
(startX,startY) = face[0],face[1]
(endX,endY) = face[2],face[3]
subFace = image[startY:endY,startX:endX]
subFace = cv2.GaussianBlur(subFace,(23, 23), 30)
# display output
# press any key to close window
cv2.imshow("face_detection", image)
cv2.waitKey()
cv2.imshow("face_detection", subFace)
# release resources
cv2.destroyAllWindows()
I finally figured out how to do it:
import cvlib as cv
import sys
from cv2 import cv2
import os
# read input image
image = cv2.imread('path')
# apply face detection
faces, confidences = cv.detect_face(image)
# print the array with the coordinates and the confidence
print(faces)
print(confidences)
# loop through detected faces
for face,conf in zip(faces,confidences):
(startX,startY) = face[0],face[1]
(endX,endY) = face[2],face[3]
# get the subface
subFace = image[startY:endY,startX:endX]
# apply gaussian blur over subfaces
subFace = cv2.GaussianBlur(subFace,(23, 23), 30)
# add the subfaces to de original image
image[startY:startY+subFace.shape[0], startX:startX+subFace.shape[1]] = subFace
cv2.imshow("face_detection", image)
cv2.waitKey()
# save output
cv2.imwrite("face_detection.jpg", image)
# release resources
cv2.destroyAllWindows()
Related
how are you all?
I am doing a project which is related to face detection. I am using dlib model for face detection. I have applied the dlib face detection model on a video clip and it is working perfectly fine. After detecting faces from a video clip I saved every frame in a new folder. Then now I am trying to align every frame with the face. The issue I am facing is that there very few frames in which dlib is not detecting the faces because of that I am getting this error
(File "align_images.py", line 22, in
images = dlib.get_face_chips(img, faces, size=180)
RuntimeError: No face were specified in the faces array.)
I have checked the output of the detector and it is not detecting any faces in the frame. I want to know how to ignore the undetected frames and save the rest in a new folder.
This is my code for aligning faces.
import cv2 as cv
import numpy as np
from PIL import Image
import dlib
import sys
import tkinter
detector = dlib.get_frontal_face_detector()
sp = dlib.shape_predictor("shape_predictor_5_face_landmarks.dat")
# img = [cv2.imread(file) for file in glob.glob(".frames_copy/*.jpg")]
img = cv.imread("./frames_copy/0054.jpg")
dets = detector(img, 1)
faces = dlib.full_object_detections()
for detection in dets:
faces.append(sp(img, detection))
window = dlib.image_window()
images = dlib.get_face_chips(img, faces, size=180)
for image in images:
window.set_image(image)
dlib.hit_enter_to_continue()
import cv2 as cv
import numpy as np
from PIL import Image
import dlib
import sys
import tkinter
import glob
from tqdm import tqdm
import os
detector = dlib.get_frontal_face_detector()
sp = dlib.shape_predictor("shape_predictor_5_face_landmarks.dat")
for f in glob.glob("face_align_samples/*"):
os.remove(f)
# img = [cv2.imread(file) for file in glob.glob(".frames_copy/*.jpg")]
# img = cv.imread("./frames_copy/0054.jpg")
aligned_faces = 0
missed_faces = 0
for index, fname in enumerate(tqdm(os.listdir('frames_copy'))):
img = cv.imread(os.path.join("frames_copy", fname))
dets = detector(img, 1)
faces = dlib.full_object_detections()
for detection in dets:
faces.append(sp(img, detection))
# window = dlib.image_window()
images = dlib.get_face_chips(img, faces, size=180)
for image in images:
aligned_faces += 1
cv.imwrite(os.path.join('face_align_samples', f'aligned_{str(index).zfill(5)}.png'), image)
missed_faces += 1
print(f'No faces were specified in the faces array for image: {fname}')
continue
print(f'Faces aligned: {aligned_faces}\nFaces missed: {missed_faces}')
I want to automate the task of entering set of images into a number generating system & before that i like to remove a dotted watermark which is common across these images.
I tried using google, tesseract & abby reader, but I found that the image part that does not contain the watermark is recognized well, but the part that is watermarked is almost impossible to recognize.
I would like to remove the watermark using image processing. I already tried few sample codes of opencv, python, matlab etc but none matching my requirements...
Here is a sample code in Python that I tried which changes the brightness & darkness:
import cv2
import numpy as np
img = cv2.imread("d:\\Docs\\WFH_Work\\test.png")
alpha = 2.5
beta = -250
new = alpha * img + beta
new = np.clip(new, 0, 255).astype(np.uint8)
cv2.imshow("my window", new)
Unusually, i dont know the watermark of this image consists how many pixels. Is there a way to get rid of this watermark OR make digits dark and lower the darkness of watermark via code?
Here is watermarked image
I am using dilate to remove the figures, then find the edge to detect watermark. Remove it by main gray inside watermark
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('test.png', 0)
kernel = np.ones((10,10),np.uint8)
dilation = cv2.dilate(img,kernel,iterations = 1)
erosion = cv2.erode(dilation,kernel,iterations = 1)
plt.imshow(erosion, cmap='gray')
plt.show()
#contour
gray = cv2.bilateralFilter(erosion, 11, 17, 17)
edged = cv2.Canny(gray, 30, 200)
plt.imshow(edged, cmap='gray')
plt.show()
I'm trying to do OCR arabic on the following ID but I get a very noisy picture, and can't extract information from it.
Here is my attempt
import tesserocr
from PIL import Image
import pytesseract
import matplotlib as plt
import cv2
import imutils
import numpy as np
image = cv2.imread(r'c:\ahmed\ahmed.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray,11,18,18)
gray = cv2.GaussianBlur(gray,(5,5), 0)
kernel = np.ones((2,2), np.uint8)
gray = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY,11,2)
#img_dilation = cv2.erode(gray, kernel, iterations=1)
#cv2.imshow("dilation", img_dilation)
cv2.imshow("gray", gray)
text = pytesseract.image_to_string(gray, lang='ara')
print(text)
with open(r"c:\ahmed\file.txt", "w", encoding="utf-8") as myfile:
myfile.write(text)
cv2.waitKey(0)
result
sample
The text for your id is in black color which makes the extraction process easy. All you need to do is threshold the dark pixels and you should be able to get the text out.
Here is a snip of the code
import cv2
import numpy as np
# load image in grayscale
image = cv2.imread('AVXjv.jpg',0)
# remove noise
dst = cv2.blur(image,(3,3))
# extract dark regions which corresponds to text
val, dst = cv2.threshold(dst,80,255,cv2.THRESH_BINARY_INV)
# morphological close to connect seperated blobs
dst = cv2.dilate(dst,None)
dst = cv2.erode(dst,None)
cv2.imshow("dst",dst)
cv2.waitKey(0)
And here is the result:
This is my output using ImageMagick TextCleaner script:
Script: textcleaner -g -e stretch -f 50 -o 30 -s 1 C:/Users/PC/Desktop/id.jpg C:/Users/PC/Desktop/out.png
Take a look here if you want to install and use TextCleaner script on Windows... It's a tutorial I made as simple as possible after few researches I made when I was in your same situation.
Now it should be very easy to detect the text and (not sure how simple) recognize it.
Hi i run this blurdetection code in python ( source : https://www.pyimagesearch.com/2015/09/07/blur-detection-with-opencv/ )
# import the necessary packages
from imutils import paths
import argparse
import cv2
def variance_of_laplacian(image):
# compute the Laplacian of the image and then return the focus
# measure, which is simply the variance of the Laplacian
return cv2.Laplacian(image, cv2.CV_64F).var()
# loop over the input images
for imagePath in paths.list_images("images/"):
# load the image, convert it to grayscale, and compute the
# focus measure of the image using the Variance of Laplacian
# method
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
fm = variance_of_laplacian(gray)
text = "Not Blurry"
# if the focus measure is less than the supplied threshold,
# then the image should be considered "blurry"
if fm < 100:
text = "Blurry"
# show the image
cv2.putText(image, "{}: {:.2f}".format(text, fm), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.imshow("Image", image)
print("{}: {:.2f}".format(text, fm))
key = cv2.waitKey(0)
with this 2173 x 3161 input file
input image
and this is the output show
the output image
The image is zoom in and dont shown full.
In the source code, they use 450 x 600 px input image :
input in source code
and this is the output :
output in source code
I think the pixels of the image influences of the output. So, how can i get the output like the output in source code to all image?
do i have to resize the input image? How to? but if I do it I'm afraid it will affect the result of his blur
Excerpt from the DOCUMENTATION.
There is a special case where you can already create a window and load image to it later. In that case, you can specify whether window is resizable or not. It is done with the function cv2.namedWindow(). By default, the flag is cv2.WINDOW_AUTOSIZE. But if you specify flag to be cv2.WINDOW_NORMAL, you can resize window. It will be helpful when image is too large in dimension and adding track bar to windows.
I just used the code placed in the question but added line cv2.namedWindow("Image", cv2.WINDOW_NORMAL) as mentioned in the comments.
# import the necessary packages
from imutils import paths
import argparse
import cv2
def variance_of_laplacian(image):
# compute the Laplacian of the image and then return the focus
# measure, which is simply the variance of the Laplacian
return cv2.Laplacian(image, cv2.CV_64F).var()
# loop over the input images
for imagePath in paths.list_images("images/"):
# load the image, convert it to grayscale, and compute the
# focus measure of the image using the Variance of Laplacian
# method
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
fm = variance_of_laplacian(gray)
text = "Not Blurry"
# if the focus measure is less than the supplied threshold,
# then the image should be considered "blurry"
if fm < 100:
text = "Blurry"
# show the image
cv2.putText(image, "{}: {:.2f}".format(text, fm), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.namedWindow("Image", cv2.WINDOW_NORMAL) #---- Added THIS line
cv2.imshow("Image", image)
print("{}: {:.2f}".format(text, fm))
key = cv2.waitKey(0)
In case you want to use the exact same resolution as the example you've given, you can just use the cv2.resize() https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#resize method or (in case you want to keep the ratio of the x/y coordinates) use the imutils class provided in https://www.pyimagesearch.com/2015/02/02/just-open-sourced-personal-imutils-package-series-opencv-convenience-functions/
You still have to decide if you want to do the resizing first. It shouldn't matter in which order you greyscale or resize.
Command you can add:
resized_image = cv2.resize(image, (450, 600))
I am trying to read an image using opencv, do some transformations (resize and offsets), then as a last step, do a crop on the image. In my final line crop_img = offset_image[0:1080, 0:1920].copy(), I expect a cropped 1920x1080 image to be created. My crop_img.size print out shows that that is correct. But, when I do an .imshow(), it is displaying the full sized, original image.
import numpy as np
import cv2 as cv
import copy
original = cv.imread("IMG_0015_guides.jpg", cv.IMREAD_UNCHANGED)
img_resize = cv.resize(original, (0,0), fx=.9, fy=.9)
rows,cols,_ = img_resize.shape
M = np.float32([[1,0,100],[0,1,50]])
offset_image = cv.warpAffine(img_resize,M,(cols,rows))
crop_img = offset_image[0:1080, 0:1920].copy()
print('img_resize {}'.format(img_resize.shape))
print('offset_image {}'.format(offset_image.shape))
print('cropped {}'.format(crop_img.shape))
cv.imshow('image',crop_img)
cv.waitKey(0)
cv.destroyAllWindows()
>>> img_resize (3110, 4666, 3)
>>> offset_image (3110, 4666, 3)
>>> cropped (1080, 1920, 3)
I'm totally baffled. Why is it not showing me the cropped 1920x1080 image?
Working with massive images can get confusing when visualizing with OpenCV's imshow.
I ran your code and it seems like its doing what you expect it to do. I suggest resizing your image again for visualization purposes only. The following code ran successfully on this image.
import numpy as np
import cv2 as cv
import copy
original = cv.imread("4k-image-tiger-jumping.jpg", cv.IMREAD_UNCHANGED)
# resize original for visualization purposes only
print('original {}'.format(original.shape))
original_resized = cv.resize(original, (0,0), fx=.1, fy=.1)
cv.imshow('original_resize',original_resized)
img_resize = cv.resize(original, (0,0), fx=.9, fy=.9)
rows,cols,_ = img_resize.shape
M = np.float32([[1,0,100],[0,1,50]])
offset_image = cv.warpAffine(img_resize,M,(cols,rows))
crop_img = offset_image[0:1080, 0:1920].copy()
print('img_resize {}'.format(img_resize.shape))
print('offset_image {}'.format(offset_image.shape))
print('cropped {}'.format(crop_img.shape))
# resize cropped for visualization purposes only
vis_r,vis_c,_ = original_resized.shape
cropped_resized = cv.resize(crop_img, (vis_c, vis_r))
cv.imshow('cropped_resized',cropped_resized)
# cv.imshow('image',crop_img)
cv.waitKey(0)
cv.destroyAllWindows()