Blur a specific part of an image - python

I have an image. Like this:
I detect a subject(which is a person in this case) & it masks the image like this:
I want the background of the subject to be blurrred. Like this:
Below is the code I have tried. the following code only blurs
import cv2
import numpy as np
from matplotlib import pyplot as plt
import os
path = 'selfies\\'
selfImgs = os.listdir(path)
for image in selfImgs:
img = cv2.imread(path+image)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
blur = cv2.blur(img,(10,10))
#canny = cv2.Canny(blur, 10, 30)
#plt.imshow(canny)
plt.imshow(blur)
j=cv2.cvtColor(blur, cv2.COLOR_BGR2RGB)
print(image)
cv2.imwrite('blurred\\'+image+".jpg",j)
Is there any way by which I can blur only specific part/parts of the image.
This project is based on https://github.com/matterport/Mask_RCNN
I can provide more information if required.
I have an approach in numpy :-
final_image = original * mask + blurred * (1-mask)

You may use np.where() method to select the pixels where you want blurred values and then replace them as:
import cv2
import numpy as np
img = cv2.imread("/home/user/Downloads/lena.png")
blurred_img = cv2.GaussianBlur(img, (21, 21), 0)
mask = np.zeros((512, 512, 3), dtype=np.uint8)
mask = cv2.circle(mask, (258, 258), 100, np.array([255, 255, 255]), -1)
out = np.where(mask==np.array([255, 255, 255]), img, blurred_img)
cv2.imwrite("./out.png", out)

As ZdaR said:
import cv2
import numpy as np
img = cv2.imread("/home/user/Downloads/lena.png")
blurred_img = cv2.GaussianBlur(img, (21, 21), 0)
mask = np.zeros((512, 512, 3), dtype=np.uint8)
mask = cv2.circle(mask, (258, 258), 100, np.array([255, 255, 255]), -1)
out = np.where(mask==np.array([255, 255, 255]), img, blurred_img)
cv2.imwrite("./out.png", out)
This is good idea but I've got same error as penta:
#ZdaR I get TypeError: Scalar value for argument 'color' is not numeric
A simple solution is to modify color value when you create Circle:
mask = cv2.circle(mask, (258, 258), 100, (255, 255,255), -1)
just CHANGE np.array([255,255,255]) to (255,255,255).

I don't know what tools you use for subject detection, but if you have a way to copy the subject, you can first copy the whole image and then blur it. finally, you can copy the subject on the blurred image.
if it gives false and true on pixels in oppose to giving borders, you can just bitwise it.

Related

How do I remove certain part of an Image in Python OpenCV?

I have been trying to isolate only the beans from the container. However, it doesn't seems to work. Please how can I achieve this OpenCV python?
I have use cv2.inrange() but I don't seem to get it.
This image is what i can give you :
Code:
import cv2
## Read
img = cv2.imread("QdMz0.jpg")
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
mask1 = cv2.inRange(rgb, (56, 0, 0), (70, 255,255))
mask2 = cv2.inRange(rgb, (5,0,0), (36, 255, 255))
## final mask and masked
mask = cv2.bitwise_or(mask1, mask2)
target = cv2.bitwise_and(img,img, mask=mask)
#cv2.imwrite("target.png", target)
plt.imshow(target)

How to translate circular cropped area in same image using OpenCV?

Original Image
Expected Output.
I am using this code for translating a specific part into the same image, but output is not changing,
import numpy as np
import cv2 as cv
img = cv.imread('eye0.jpg', 0)
rows, cols = img.shape
roi = img[200: 300, 360: 450]
M = np.float32([[1, 0, 100], [0, 1, 50]])
dst = cv.warpAffine(roi, M, roi.shape)
cv.imshow('img', img)
cv.imshow('img', dst)
cv.waitKey(0)
cv.destroyAllWindows()
I see no changes from original image. How can I do so? Moreover, as an openCV newbie I would like to know which function should I use/explore here to get my purpose served?
Copy() function can help you instead of warpAffine(). You can check here also:
Here is output and code:
import numpy as np
import cv2 as cv
img = cv.imread('eye.jpg', 1)
#rows, cols = img.shape
roi = img[80: 100, 140: 160]
img2 = img.copy()
img2[95:115, 140:160]=roi
cv.imshow('img', img)
cv.imshow('imaag', img2)
cv.waitKey(0)
cv.destroyAllWindows()
**Image after warp affine tranformation... but for circling the part it seem difficult..
**
import numpy as np
import cv2 as cv
img = cv.imread('eye.jpg')
roi = img[78: 100, 130: 160]
M = np.float32([[1, 0, 6], [0, 1, 4]])
dst = cv.warpAffine(roi, M, (30, 22))
img[80:102, 132:162] = dst
cv.imwrite("newimage.jpg",img)
cv.imshow('img', img)
cv.imshow('img1',dst)
cv.waitKey(0)
cv.destroyAllWindows()

How to detect width of object in picture

I must write the program to detect width of object. I understand that without reference object it will be expressed in pixels but it's enough for me. The background will always be white. I have problem what i should to do right now.
I will be sow greatfull for Your help !
enter image description here
import numpy as np
import imutils
import cv2
import math
# Function to show array of images (intermediate results)
def show_images(images):
for i, img in enumerate(images):
cv2.imshow("image_" + str(i), img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Read image and preprocess
image = cv2.imread('44.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (9, 9), 0)
edged = cv2.Canny(blur, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)
show_images([blur, edged])
#show_images([cnts, edged])
Welcome to Stack Overflow!
Since your're using OpenCV, finding the image dimensions is as simple as the code below.
import numpy as np
import cv2
img = cv2.imread('image.png')
dimension = img.shape
height = img.shape[0]
width = img.shape[1]
channels = img.shape[2]
Read more about this here:

How can i get the rgb color values from inside of a contour in image using opencv?

I know here already some questions were asked but they did't help me to solve my problem. I will appreciate any help to solve my problem.
I'm new to opencv.
I have an image and apply some code to get contours from image. Now i want to get the RGB color values from detected contours. How can i do that?
I do research on it and find that it could be solved by using contours so i try to implement contours and now finally i want to get the color values of the contours.
Here is my Code:
import cv2
import numpy as np
img = cv2.imread('C:/Users/Rizwan/Desktop/example_strip1.jpg')
img_hsv = cv2.cvtColor(255-img, cv2.COLOR_BGR2HSV)
lower_red = np.array([40, 20, 0])
upper_red = np.array([95, 255, 255])
mask = cv2.inRange(img_hsv, lower_red, upper_red)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
color_detected_img = cv2.bitwise_and(img, img, mask=mask)
print(len(contours))
for c in contours:
area = cv2.contourArea(c)
x, y, w, h = cv2.boundingRect(c)
ax = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 0), 2)
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
im = cv2.drawContours(color_detected_img, [box], -1, (255, 0, 0), 2)
cv2.imshow("Cropped", color_detected_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
I expect the output should be the RGB values of the detected color inside the contours.
As asked in the comments, here's a possible solution to extract the BGR(!) values from the pixels of an image inside a before found contour. The proper detecting of the desired, colored stripes is omitted here as also discussed in the comments.
Having an image and a filled mask of a contour, for example from cv2.drawContours, we can simply use NumPy's boolean array indexing by converting the (most likely uint8) mask to an bool_ array.
Here's a short code snippet, that uses NumPy's savetxt to store all values in some txt file:
import cv2
import numpy as np
# Some dummy image
img = np.zeros((100, 100, 3), np.uint8)
img = cv2.rectangle(img, (0, 0), (49, 99), (255, 0, 0), cv2.FILLED)
img = cv2.rectangle(img, (50, 0), (99, 49), (0, 255, 0), cv2.FILLED)
img = cv2.rectangle(img, (50, 50), (99, 99), (0, 0, 255), cv2.FILLED)
# Mask of some dummy contour
mask = np.zeros((100, 100), np.uint8)
mask = cv2.fillPoly(mask, np.array([[[20, 20], [30, 70], [70, 50], [20, 20]]]), 255)
# Show only for visualization purposes
cv2.imshow('img', img)
cv2.imshow('mask', mask)
# Convert mask to boolean array
mask = np.bool_(mask)
# Use boolean array indexing to get all BGR values from img within mask
values = img[mask]
# For example, save values to txt file
np.savetxt('values.txt', values)
cv2.waitKey(0)
cv2.destroyAllWindows()
The dummy image looks like this:
The dummy contour mask looke like this:
The resulting values.txt has some >1000 entries, please check yourself. Attention: Values are BGR values; e.g. prior converting the image to RGB is needed to get RGB values.
Hope that helps!

Reduce unwanted noise of image from phone by open-cv

I have a trouble with my image was taken by phone. I can't reduce unwanted noise of my photo
I have tried to increase contrast and also brightness but it's not effective
img = cv2.imread(image_path, 0)
blur = cv2.GaussianBlur(img, (5, 5), 0)
thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11,
2) # Convert Image To Binary
plt.imshow(img)
This is my original photo
This is my photo after processing
This is my expected photo
You have used the right thresholding method to produce the binary image from the original image, whereas it needs some optimization to get the best result:
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('aa.jpg', 0)
blur = cv.medianBlur(img,11)
# blur = cv.GaussianBlur(img,(11,11),0)
thresh = cv.adaptiveThreshold(blur,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv.THRESH_BINARY, 31, 4)
plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(thresh)
plt.show()
I didn't understand if you need also to filter off the pen marks, because in that case you need something more complex.
Anyway in your code the mistake is just in
plt.imshow(img)
you just plot your original image and not the filtered one...try this
plt.imshow(blur)
or this
plt.imshow(thresh)
and check the results

Categories

Resources