I tried to mask image by its color using opencv.
import cv2
import numpy as np
import matplotlib.pyplot as plt
After importing libraries, I load the image
img = cv2.imread('gmaps.jpg')
image = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
plt.imshow(image);
Turn the color into hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
plt.imshow(hsv);
Masking process
low_orange = np.array([44, 6, 100])
high_orange = np.array([44, 24, 99])
masking = cv2.inRange(hsv,low_orange, high_orange)
plt.imshow(masking);
The result isn't what I expected.
Image :
Result :
EDIT: I want to mask the building only. Instead I got the result of masking all of the frame.
Using my answer from here I manage to extract the right values for you
Code:
frame = cv2.imread("Xv6gx.png")
blurred_frame = cv2.GaussianBlur(frame, (5, 5), 0)
hsv = cv2.cvtColor(blurred_frame, cv2.COLOR_BGR2HSV)
lower = np.array([4, 0, 7])
upper = np.array([87, 240, 255])
mask = cv2.inRange(hsv, lower, upper)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for contour in contours:
area = cv2.contourArea(contour)
if area > 5000:
# -- Draw Option 1 --
cv2.drawContours(frame, contour, -1, (0, 255, 0), 3)
# -- Draw Option 2--
# rect = cv2.boundingRect(contour)
# x, y, w, h = rect
# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Mask", mask)
cv2.imshow("Frame", frame)
cv2.waitKey(0)
Final Results:
I wouldn't expect the low Value (100) to exceed the high Value (99).
Also, OpenCV uses a range of 0..180 for Hue rather than 0..360, so you likely need to divide your 44 by 2.
Related
I need to find several objects (let's say up to 10 pieces) in the picture. Objects must be of a certain color.
Using this code and searching for contours, it turns out to find only the midpoint between several objects, but you need to find the coordinates of each object separately.
Maybe somehow you can make a limit on the size of one object? (i.e. the object must not be less than 100x100 pixels, and not more than 300x300 pixels)
import cv2
import matplotlib.pyplot as plt
import pyautogui as pg
output = '1.jpg'
flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
nemo = cv2.imread(output, cv2.IMREAD_COLOR) #output, cv2.IMREAD_COLOR)
nemo = cv2.cvtColor(nemo, cv2.COLOR_BGR2RGB)
hsv_nemo = cv2.cvtColor(nemo, cv2.COLOR_RGB2HSV)
light_orange = (92,128,224)
dark_orange = (109,255,255)
#
mask = cv2.inRange(hsv_nemo, light_orange, dark_orange)
result = cv2.bitwise_and(nemo, nemo, mask=mask)
#
moments = cv2.moments(mask, 1)
x_moment = moments['m01']
y_moment = moments['m10']
area = moments['m00']
y = int(x_moment / area)
x = int(y_moment / area)
pg.moveTo(x,y)
plt.imshow(result)
plt.imsave('result.jpg',result)
plt.show()
#print(x,y)
gray = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(result, contours, -1, (0, 0, 255), 3)
cv2.imshow('img', result)
cv2.waitKey(0)
#print (len(contours[0]))
#print (len(contours[1]))
enter image description here
iam trying to apply a heat map on a selected portion[people's face] of my picture. Here is what i had done so far...
the rectangle will be applied to the face .
the face will be cropped
heat map will be applied to the cropped image.
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
crop_img = image[y:y+h, x:x+w]
# Cropping Area
# Color Mapping Area
images = cv2.imread(crop_img, 0)
colormap = plt.get_cmap('inferno')
heatmap = (colormap(images) * 2**16).astype(np.uint16)[:,:,:3]
heatmap = cv2.cvtColor(heatmap, cv2.COLOR_RGB2BGR)
# Saving Color Map
img_names = "heatimage{}.png".format(i)
cv2.imwrite(img_names, heatmap)
print("{} written!".format(img_names))
img = cv2.imread(img_names,0)
cv2.imshow('heatmap{}'.format(i),heatmap)
i was able to save the cropped image and rectangle pointing faces separately but i need
1. to make the rectangle to be a heat map ,without cropping separately,in my original image.
2. other part of the image has to be normal
EDITED
Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
crop_img = image[y:y+h, x:x+w]
sample = cv2.imread("sample.jpg",cv2.COLOR_BGR2GRAY)
colormap = cm.get_cmap('inferno', 256)
cmp = cm.ScalarMappable(cmap='inferno')
# create 1D float gradient from 0 to 1 with 256 increments
# convert to rgba in range 0 to 255 (via bytes=True)
# remove alpha channel and reshape to 256x1 3 channel from (256, 4)
# convert rgb to bgr
cmap = np.linspace(0, 1, 256, endpoint=True)
cmap = cmp.to_rgba(cmap, bytes=True)
cmap = cmap[:, 0:-1].reshape((256, 1, 3))
cmap = cv2.cvtColor(cmap, cv2.COLOR_RGB2BGR)
# apply color map to crop
crop_mapped = cv2.applyColorMap(crop_img, cmap)
# put color mapped crop back into input
result = sample.copy()
result = cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)
result[y:y+h, x:x+w] = crop_mapped
# save result
cv2.imwrite('IRimage.jpg', result)
# show result
cv2.imshow("result", result)
i+=1
cv2.imshow("Faces found", image)
If i have more than one face , how can i apply color filter to both the faces?
If I understand correctly, you're trying to display the portion of a heatmap that's on the face of a person.Try this
alpha = 0.5
image[y:y+h, x:x+w] = alpha * image[y:y+h, x:x+w] + (1 - alpha) * heatmap[y:y+h, x:x+w]
cv2.imshow("preview", image)
I believe that you will have to crop the image, apply the colormap to the cropped image, then put the color mapped crop image back into your original. I do not think there is a way to apply a colormap directly to a portion of an image.
Here is how I do the above in Python/OpenCV.
Read the input as grayscale
Crop the image where you want it to be color mapped
Load the colormap from Matplotlib and convert it to a BGR image
Apply the colormap to the cropped image
Convert the input to 3 channel gray and insert the color mapped cropped image back in the correct location.
Save the results
Input:
import cv2
import numpy as np
import matplotlib.cm as cm
# read image and convert to gray
img = cv2.imread('redhat_gray.jpg', cv2.COLOR_BGR2GRAY)
# crop image
crop = img[140:240, 70:170]
# get colormap from matplotlib and normalize
colormap = cm.get_cmap('inferno', 256)
cmp = cm.ScalarMappable(cmap='inferno')
# create 1D float gradient from 0 to 1 with 256 increments
# convert to rgba in range 0 to 255 (via bytes=True)
# remove alpha channel and reshape to 256x1 3 channel from (256, 4)
# convert rgb to bgr
cmap = np.linspace(0, 1, 256, endpoint=True)
cmap = cmp.to_rgba(cmap, bytes=True)
cmap = cmap[:, 0:-1].reshape((256, 1, 3))
cmap = cv2.cvtColor(cmap, cv2.COLOR_RGB2BGR)
#print(cmap)
# apply color map to crop
crop_mapped = cv2.applyColorMap(crop, cmap)
# put color mapped crop back into input
result = img.copy()
result = cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)
result[140:240, 70:170] = crop_mapped
# save result
cv2.imwrite('redhat_gray_rectangle_inferno.jpg', result)
# show result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result:
I would like to divide image based on the bounding boxes. Image consist of column name and row, but column don't have any border so depends on gap it should divide
I am able to identify the bounding box, I am not understanding on what bases image should be cropped
large = cv2.imread("../forms/demo_1/crop/abc.jpg")
rgb = large
small = cv2.cvtColor(rgb, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
grad = cv2.morphologyEx(small, cv2.MORPH_GRADIENT, kernel)
_, bw = cv2.threshold(grad, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 1))
connected = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)
contours, hierarchy = cv2.findContours(connected.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
mask = np.zeros(bw.shape, dtype=np.uint8)
for idx in range(len(contours)):
x, y, w, h = cv2.boundingRect(contours[idx])
mask[y:y+h, x:x+w] = 0
cv2.drawContours(mask, contours, idx, (255, 255, 255), -1)
r = float(cv2.countNonZero(mask[y:y+h, x:x+w])) / (w * h)
if r > 0.4 and w > 3 and h > 8:
cv2.rectangle(rgb, (x, y), (x+w-1, y+h-1), (0, 255, 0), 2)
print(x,y,x+w,y+h)
cv2.imshow('rects', rgb)
cv2.waitKey()
cv2.destroyAllWindows()
Input:
Output:
This is how you crop a rectangle from an image in OpenCV (see also this tutorial):
import cv2
large = cv2.imread("../forms/demo_1/crop/abc.jpg")
# ... your code
for idx in range(len(contours)):
# ... your code to calculate x, y, w, g
# example values. Use your calculated values here
x, y, w, h = 0, 0, 60, 250
crop = large[x:x+w, y:y+h]
cv2.imshow('crop', crop)
cv2.waitKey()
My code so far. I want to crop out the white in the image.
import cv2
import numpy as np
image = cv2.imread('myimage.jpg')
image2 = np.ones((255, 255, 4))
for i in range(255):
for j in range(255):
if image[i,j,0] == 255:
image2[i, j, :] = np.append(image[i, j, :], 1)
else:
image2[i, j, :] = np.append(image[i, j, :], 1)
cv2.imwrite('image2.png', image2)
But it just produces an empty plot.
This should be enough:
The background of the website is white, so "right click" the Output and "open image in new tab" and you'll see that it is transparent :)
import cv2
import numpy as np
# read the image
image_bgr = cv2.imread('image_bgr.png')
# get the image dimensions (height, width and channels)
h, w, c = image_bgr.shape
# append Alpha channel -- required for BGRA (Blue, Green, Red, Alpha)
image_bgra = np.concatenate([image_bgr, np.full((h, w, 1), 255, dtype=np.uint8)], axis=-1)
# create a mask where white pixels ([255, 255, 255]) are True
white = np.all(image_bgr == [255, 255, 255], axis=-1)
# change the values of Alpha to 0 for all the white pixels
image_bgra[white, -1] = 0
# save the image
cv2.imwrite('image_bgra.png', image_bgra)
Input:
Output ("right click" >> "open in new tab"):
I want to detect paper sheet from image. i applied medianBlur, Canny , dilate, threshold, etc. algorithms to find.i am able to find sheet but don't know how to crop rectangle and apply transformation
answer sheet
This my code
import numpy as np
import cv2
image = cv2.imread('im_1.jpg')
image = cv2.resize(image, (800, 600))
draw = np.zeros_like(image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
thresh = cv2.erode(thresh, kernel, iterations=4)
thresh = cv2.dilate(thresh, kernel, iterations=4)
im, cnts, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
max_area = -1
max_c = 0
for i in range(len(cnts)):
contour = cnts[i]
area = cv2.contourArea(contour)
if (area > max_area):
max_area = area
max_c = i
contour = cnts[max_c]
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image, [box],-1, (0, 255, 0), 2)
cv2.imshow('Sheet', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
result of code:
result
There are some minor flaws in your approach. The following code will help. I have mentioned the changes made as well.
Code:
import numpy as np
import cv2
image = cv2.imread('C:/Users/Jackson/Desktop/score.jpg')
#--- Resized the image to half its dimension maintaining the aspect ratio ---
image = cv2.resize(image, (0, 0), fx = 0.5, fy = 0.5)
draw = np.zeros_like(image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#--- I found the inverse binary image, because contours are found for objects in white. Since the border of the page is in black you have to invert the binary image. This is where it went wrong.
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)
#--- I did not perform any morphological operation ---
im, cnts, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
max_area = -1
max_c = 0
for i in range(len(cnts)):
contour = cnts[i]
area = cv2.contourArea(contour)
if (area > max_area):
max_area = area
max_c = i
contour = cnts[max_c]
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image, [box],-1, (0, 255, 0), 2)
cv2.imshow('Sheet', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result: