Pulkit
Pulkit

Reputation: 706

Blur from OpenCV in Region of Interest

I am trying create a circle and blur the contents in OpenCV. However, I am able to make the circle, but I am not able to blur that part. My code is given below. Please help me out

import io
import picamera
import cv2
import numpy as np
import glob
from time import sleep
from PIL import ImageFilter


image = cv2.imread('/home/pi/Desktop/cricle-test/output_0020.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faceCascade = cv2.CascadeClassifier('/home/pi/Desktop/Image-Detection-test/haarcascade_frontalface_alt.xml')

faces = faceCascade.detectMultiScale(
    gray,
    scaleFactor=1.2,
    minNeighbors=5,
    minSize=(30, 30),
    flags = cv2.cv.CV_HAAR_SCALE_IMAGE
)
print "Found {0} faces!".format(len(faces))

# Draw a circle around the faces and blur
for (x, y, w, h) in faces:

    sub = cv2.circle(image, ( int((x + x + w )/2), int((y + y + h)/2 )), int (h / 2), (0, 255, 0), 5)
    cv2.blur(image(x,y,w,h),(23,23), 40000)
    cv2.imwrite("/home/pi/Desktop/cricle-test/output_0020.jpg" ,image)

Upvotes: 3

Views: 9088

Answers (1)

api55
api55

Reputation: 11420

For it to work you need to do a couple of things, first cv2.blur needs a destination and not a number. This can be achieved with:

image[y:y+h, x:x+w] = cv2.blur(image[y:y+h, x:x+w] ,(23,23))

Since you are saving the image to the same file in every loop, you can just save it after the loop.

Since you wanted a circular bur, you need to create a circular mask, then apply it to the image, here is how your code will look like (only the loop part):

# create a temp image and a mask to work on
tempImg = image.copy()
maskShape = (image.shape[0], image.shape[1], 1)
mask = np.full(maskShape, 0, dtype=np.uint8)
# start the face loop
for (x, y, w, h) in faces:
  #blur first so that the circle is not blurred
  tempImg [y:y+h, x:x+w] = cv2.blur(tempImg [y:y+h, x:x+w] ,(23,23))
  # create the circle in the mask and in the tempImg, notice the one in the mask is full
  cv2.circle(tempImg , ( int((x + x + w )/2), int((y + y + h)/2 )), int (h / 2), (0, 255, 0), 5)
  cv2.circle(mask , ( int((x + x + w )/2), int((y + y + h)/2 )), int (h / 2), (255), -1)

# oustide of the loop, apply the mask and save
mask_inv = cv2.bitwise_not(mask)
img1_bg = cv2.bitwise_and(image,image,mask = mask_inv)
img2_fg = cv2.bitwise_and(tempImg,tempImg,mask = mask)
dst = cv2.add(img1_bg,img2_fg)

cv2.imwrite("/home/pi/Desktop/cricle-test/output_0020.jpg" ,dst)

This seems to work, at least in my test, you may try adjusting the kernel size (this (23,23) in the blur) to get less or more blurred image, for example, try this code with (7,7) it will have more details.

Update

If you want to use ellipses instead of circles just change the circle instruction to:

cv2.ellipse(mask , ( ( int((x + x + w )/2), int((y + y + h)/2 )),(w,h), 0), 255, -1)

The same way you can change it to a rectangle, polygon, or any other shape.

Upvotes: 12

Related Questions