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

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()

Related

np.where doesnt work with specific colors

im trying to make the template image black except for the red rectangle which has BGR [0, 4, 95]. below code works for other colored rectangles but i figured it wont work sometimes with specific BGR. (in this case, it wont work with [0, 4, 95]) i have no idea why it wont.
can anyone tell me what im missing?
import numpy as np
import cv2
output_color = [0,4,95]
img = cv2.imread('1.png', cv2.IMREAD_UNCHANGED)
img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
img = np.where(np.all(img == output_color, axis=2, keepdims=True), output_color, [0, 0, 0])
img = img[..., 0].astype('uint8')
cv2.imshow("output", img)
cv2.waitKey()
cv2.destroyAllWindows()
result i get
result i want

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 cv2.imshow large size images?

I am trying to cv2.imshow my images for perspective transformation.
But, my image is very big, so I cannot see the whole picture:
How could I fix this problem?
The below is my code:
import cv2
import os
import numpy as np
image_path = "1.jpg"
filename, ext = os.path.splitext(os.path.basename(img_path))
ori_img = cv2.imread(img_path)
src = []
# mouse callback handler
def mouse_handler(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONUP:
img = ori_img.copy()
src.append([x, y])
for xx, yy in src:
cv2.circle(img, center=(xx, yy), radius=5, color=(0, 255, 0), thickness=-1, lineType=cv2.LINE_AA)
cv2.imshow('img', img)
# perspective transform
if len(src) == 4:
src_np = np.array(src, dtype=np.float32)
width = max(np.linalg.norm(src_np[0] - src_np[1]), np.linalg.norm(src_np[2] - src_np[3]))
height = max(np.linalg.norm(src_np[0] - src_np[3]), np.linalg.norm(src_np[1] - src_np[2]))
dst_np = np.array([
[0, 0],
[width, 0],
[width, height],
[0, height]
], dtype=np.float32)
M = cv2.getPerspectiveTransform(src=src_np, dst=dst_np)
result = cv2.warpPerspective(ori_img, M=M, dsize=(width, height))
cv2.imshow('result', result)
cv2.imwrite(r'projetive_image/%s_result%s' % (filename, ext), result)
# main
cv2.namedWindow('img')
cv2.setMouseCallback('img', mouse_handler)
cv2.imshow('img', ori_img)
cv2.waitKey(0)
Before displaying the image, you could simply downsize the image using cv2.resize or if you wanted to maintain aspect ratio, you can use imutils.resize. Another method is to simply save the image using cv2.imwrite then open it in your system's native image viewer.
import cv2
import imutils
image = cv2.imread('1.jpg')
# Downsize without aspect ratio
image1 = cv2.resize(image, (500,500), interpolation=cv2.INTER_AREA)
# Downsize and maintain aspect ratio
image2 = imutils.resize(image, width=800)
cv2.imshow('image1', image1)
cv2.imshow('image2', image2)
cv2.waitKey()
Instead of resizing your image before displaying, you can also resize the window, that displays the image, by using cv2.resizeWindow. Therefore, you need to set the cv2.WINDOW_NORMAL WindowFlag in your cv2.namedWindow call.
That'd be a minimal example:
import cv2
import numpy as np
img = np.random.randint(0, 255, (4000, 3000, 3), np.uint8)
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 800, 600)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Hope that helps!
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.1
NumPy: 1.18.1
OpenCV: 4.2.0
----------------------------------------

Display the bottom image of the line and cut the upper image using Opencv

I am trying to crop the live video diagonally. With the help of cv.line, I have mentioned the dimensions and my goal is to display the video of the lower side of the line I have drawn and the upper video should be cropped,
As a beginner, I was just able to draw a line using the following code:
import cv2
cv2.namedWindow("preview")
vc = cv2.VideoCapture(0)
if vc.isOpened(): # try to get the first frame
rval, frame = vc.read()
else:
rval = False
while rval:
cv2.imshow("preview", frame)
rval, frame = vc.read()
key = cv2.waitKey(20)
if key == 27: # exit on ESC
break
else:
cv2.line(img=frame, pt1=(700,5), pt2=(5, 450), color=(255, 0, 0), thickness=1, lineType=8, shift=0)
vc.release()
cv2.destroyWindow("preview")
Output:
Suggestion on this will be very helpful
Here's the code that'll mask out the points above the line. I've added comments here so you can follow what's going on. There are faster ways to do this, but I wanted something that would be easily readable.
import cv2
import matplotlib.pyplot as plt
import numpy as np
path = r"path\to\img"
img = cv2.imread(path)
#plt.imshow(img)
#plt.show()
pt1 = (86, 0) #ensure this point exists within the image
pt2 = (0, 101) #ensure this point exists within the image
cv2.line(img, pt1, pt2, (255, 255, 255))
#plt.imshow(img)
#plt.show()
#slope of line
m = float(pt2[1] - pt1[1])/float(pt2[0] - pt1[0])
c = pt1[1] - m*pt1[0]
#create mask image
mask1 = np.zeros(img.shape, np.uint8)
#for every point in the image
for x in np.arange(0, 87):
for y in np.arange(0, 102):
#test if point exists above the line,
if y > m*x + c:
mask1[y][x] = (255, 255, 255)
#plt.imshow(mask1)
#plt.show()
fin_img = cv2.merge((img[:, :, 0], img[:, :, 1], img[:, :, 2], mask1[:,:, 0]))
#plt.imshow(fin_img)
#plt.show()
cv2.imwrite('output.png', fin_img)
To crop images, I use a mask and cv2.bitwise_and().
Source Image:
The mask:
# Create a mask image with a triangle on it
y,x,_ = img.shape
mask = np.zeros((y,x), np.uint8)
triangle_cnt = np.array( [(x,y), (x,0), (0,y)] )
cv2.drawContours(mask, [triangle_cnt], 0, 255, -1)
The output:
img = cv2.bitwise_and(img, img, mask=mask)

Blur a specific part of an image

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.

Categories

Resources