I currently have the following code, it searches for a range of colors (blue) and is replacing it with a specific color, however, I would like to replace it with the closest color in the image, not the closest in the palette but in the image.
How can I do this?
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = cv2.imread('test5.jpeg')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_blue = np.array([80,50,50], dtype="uint8")
upper_blue = np.array([101,255,255], dtype="uint8")
mask = cv2.inRange(hsv, lower_blue, upper_blue)
#image[mask > 0] = (183, 213, 247)
plt.figure()
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
mask = cv2.inRange(hsv, lower_blue, upper_blue)
mask = cv2.bitwise_and(image, image, mask=mask)
gray_mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
image = cv2.inpaint(image, gray_mask, 100, flags=cv2.INPAINT_TELEA)
I could solve my problem using the inpaint method.
https://www.pyimagesearch.com/2020/05/18/image-inpainting-with-opencv-and-python/
Related
I extracted green color in image with cv2.inRange().
But, The colors of the extracted images were all different.
like this --> enter image description here
I want to change extracted image's color to same.
Please help me....
This is my code.
import numpy as np
import cv2
img = cv2.imread('test_img.jpg')
height, width = img.shape[:2]
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_green = (35,45,0,0)
upper_green = (80, 255, 255,0)
img_mask = cv2.inRange(img_hsv, lower_green, upper_green)
img_result = cv2.bitwise_and(img, img, mask = img_mask)
cv2.imshow('color',img_result)
Output
enter image description here
You need to zero the B and R dimensions of the image, as follows:
import numpy as np
import cv2
img = cv2.imread('test_img.jpg')
height, width = img.shape[:2]
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_green = (35,45,0,0)
upper_green = (80, 255, 255,0)
img_mask = cv2.inRange(img_hsv, lower_green, upper_green)
img_result = cv2.bitwise_and(img, img, mask = img_mask)[:, :, 1]
img[:, :, 0] = 0
img[:, :, 2] = 0
img[:, :, 1] = img_result
cv2.imshow('color', img)
cv2.waitKey(0)
or if you want a simpler way to output the image, you can use the matplotlib.pyplot, as follows:
import matplotlib.pyplot as plt
plt.imshow(img)
Cheers
I have some images which are in form of a grid. I have a code that works to find the largest rectangle in the grid. However it works in some images and completely fails in doing so in others, I need help fine-tuning the code to work in all the cases. Ideally I'd like the contours exactly on the border.
The code:
import cv2
import numpy as np
img = cv2.imread('3.jpg')
frame = cv2.resize(img,(1000,500))
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_red = np.array([0, 10, 120])
upper_red = np.array([15, 255, 255])
mask = cv2.inRange (hsv, lower_red, upper_red)
cv2.imshow("a",mask)
cv2.waitKey(0)
contours, _ = cv2.findContours(mask.copy(),
cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
if len(contours) > 0:
red_area = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(red_area)
cv2.rectangle(frame,(x, y),(x+w, y+h),(0, 0, 255), 2)
cv2.imshow('frame', frame)
cv2.imshow('mask', mask)
cv2.waitKey(0)
Image in which it works correctly:
Image in which the code does not work:
your problem in finding the max contour after thresolding can be solved simply by identifying the max contour corners:
import cv2
import numpy as np
img = cv2.imread('2.png')
frame = cv2.resize(img,(1000,500))
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_red = np.array([0, 10, 120])
upper_red = np.array([15, 255, 255])
mask = cv2.inRange (hsv, lower_red, upper_red)
y0 = np.min(np.where(mask>0)[0])
x0 = np.min(np.where(mask>0)[1])
y1 = np.max(np.where(mask>0)[0])
x1 = np.max(np.where(mask>0)[1])
cv2.rectangle(frame,(x0, y0),(x1, y1),(0, 0, 255), 2)
cv2.imshow('frame', frame)
cv2.imshow('mask', mask)
cv2.waitKey(0)
I tried a code from stackoverflow but it shows black color for me. what I want to do is:
Get Tomatoes white and other things black of this image
To get red colors out of this image I used this code:
import cv2
import numpy as np
img = cv2.imread('test.png')
img = np.copy(img)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_red = np.array([217, 25, 0])
upper_red = np.array([254, 217, 196])
mask = cv2.inRange(hsv, lower_red, upper_red)
#mask = cv2.bitwise_not(mask)
cv2.imwrite('mask.png', mask)
cv2.destroyAllWindows()
result is this
thank you for reading
The following adaptation from your code:
import cv2
import numpy as np
img = cv2.imread('test2.png')
img = np.copy(img)
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
lower_red = np.array([225, 0, 0])
upper_red = np.array([255, 200, 200])
mask = cv2.inRange(rgb, lower_red, upper_red)
cv2.imwrite('mask.png', mask)
cv2.destroyAllWindows()
produces this output:
I simply removed the conversion to HSV (which is not necessary and I guess your initial lower and upper limits where thought to be for RGB anyway?). I played around a bit with the limits, but I guess, if you tinker a bit more with them, you can get better results.
Try this HSV mask:
import cv2
import numpy as np
img = cv2.imread("tomato.jpg")
lower = np.array([0, 55, 227])
upper = np.array([21, 255, 255])
mask = cv2.inRange(cv2.cvtColor(img, cv2.COLOR_BGR2HSV), lower, upper)
cv2.imshow("Image", mask)
cv2.waitKey(0)
Output:
I may be overshooting a bit but I'm trying to use a mask generated from my image and subtract it from the main image. I'm quite open to instead extracting the characters but am not sure how to collect the entire blue sample, I haven't that correct balance yet.
The page here demonstrates the inverse of what I'm trying to achieve.
Base image
The mask utilizing hsv bounds then inverting it to show it better
Darkening it
I wish to now take that mask and remove it from the main image.
import cv2
import numpy as np
import random as rng
from PIL import Image
from PIL import ImageOps
from utils import helper
image_name = 'capt13.jpg'
img = cv2.imread(image_name)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_red = np.array([0,120,70])
upper_red = np.array([10,255,255])
lower_mask = cv2.inRange(hsv, lower_red, upper_red)
lower_red = np.array([160,120,70])
upper_red = np.array([180,255,255])
upper_mask = cv2.inRange(hsv, lower_red, upper_red)
'''
lower_blue = np.array([80,40,30])
upper_blue = np.array([140,255,255])
lower_mask = cv2.inRange(hsv, lower_blue, upper_blue)
lower_blue = np.array([240,220,200])
upper_blue = np.array([360,255,255])
upper_mask = cv2.inRange(hsv, lower_blue, upper_blue)
'''
mask = lower_mask + upper_mask
res_lines = cv2.bitwise_and(img,img, mask= mask)
# Keep the inverted
image = Image.fromarray(res_lines)
image.save('res.png')
inverted = ImageOps.invert(image)
inverted = inverted.convert('L')
inverted.save('inverted.png')
binary = np.array(inverted)
for row in range(len(binary)):
for col in range(len(binary[row])):
if binary[row][col] != 255:
binary[row][col] = 0
binary_image = Image.fromarray(binary)
binary_image.save('binary.png')
Extracting the Blue (As stated above that I'm open to a better solution for this)
The mask utilizing hsv bounds then inverted it
Darkening it
Straight subtraction works, provided both images are the same size:
im = cv2.imread("image.png")
mask = cv2.imread("mask.png")
diff_im = im - im2
Alternatively, you can use OpenCV's built in subtract, which does an element-wise subtraction:
diff_im = cv2.subtract(im, im2)
As a final thought, you should also try absdiff, as it will convert negative results to zeroes, which may be what you want.
diff_im = cv2.absdiff(im, im2)
I'm using Opencv python in raspberry pi, to analize a heatmap, i'm looking for color red, which represents the highest temperature, i need to detect if in an specific area exist red color, in case it does i can use this information to activate a condition, i'm using a heatmap like this:
for the red color detection i'm using this code:
import cv2
import numpy as np
while(1):
# Take each frame
frame = cv2.imread('heatmap.png')
# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_red = np.array([-20, 100, 100])
upper_red = np.array([13, 255, 255])
# Threshold the HSV image to get only blue colors
mask = cv2.inRange(hsv, lower_red, upper_red)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('heatmap',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
the code above give me al the pixels in red, but i need to determine if the heatmap contour is red, i mean the image contour or border would be a red color not permited area, does anyone how i can do that?
Your HSV range is not right. For red, (0,20,20)~(8,255,255), (170,20,20) ~ (180,255,255).
Here is my result:
The code:
#!/usr/bin/python3
# 2018/05/16 13:54:09
import cv2
import numpy as np
img = cv2.imread('heatmap.png')
# Convert BGR to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask1 = cv2.inRange(hsv, (0,20,20), (8,255,255))
mask2 = cv2.inRange(hsv, (170,20,20), (180,255,255))
mask = cv2.bitwise_or(mask1, mask2)
dst = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow("dst", dst)
cv2.imwrite("__.png", dst)
cv2.waitKey()
Some useful links:
Choosing the correct upper and lower HSV boundaries for color detection with`cv::inRange` (OpenCV)
How to define a threshold value to detect only green colour objects in an image :Opencv