问题
What is My Issue?
I have generated depth maps from monocular images using DenseDepth. Some of my results are below. I need help masking the darkest shades/ the darkest value of greys in a given range in the depth map.
I would like to be able to give two hex values ie. #6E6E6E and #000000 and for the mask to select all the values in-between and then generate a black and white mask.
What Have I Tried?
After some research I came across this here: https://medium.com/@offsouza/segmentando-objetos-pela-cor-opencv-487d5181b473 (Use on Chrome for Google Translate as it is in Spanish I think)
Here is the depth map which I tried to use in this specific example:
Here is the python code which I used:
import cv2
import numpy as np
image = cv2.imread('DepthMap.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
blur = cv2.medianBlur(hsv ,11)
lower = np.array([0,0,35])
upper = np.array([0,0,44])
mask = cv2.inRange(blur, lower, upper)
res = cv2.bitwise_and(image,image, mask= mask)
cv2.imshow("mask ",mask)
cv2.imshow('stack', np.hstack([image, res]))
cv2.waitKey(0)
This is the output of the code:
This doesn't ,however, allow me to give two hex values and then select everything in-between but instead I need to specify the upper and lower values. To do this I used this script here: https://github.com/offsouza/color-segmentation/blob/master/get_color.py.
As you can probably tell, this isn't the best result- at all- to the extent that it doesn't work. I have very little knowledge in this field so I would really appreciate if you could help me!
Edit: this is a hand drawn representation of an expected outcome:
https://i.ibb.co/n8JkSf3/C051-EAE8-C114-4-E90-8938-25-A8-C79-A4-A7-E.jpg
回答1:
To better solve my issue and allow it to be generalised across a wide range of depth maps I took a different approach to reach the same objective.
Instead of selecting upper and lower colour ranges which seemed to give inconsistent results when tested on various images. I chose to use global thresholding instead.
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html
I further adapted my code to take the average (not dominant) shade of grey aka brightness, and divided this by 2. Thus giving me the 25% darkest areas of grey being highlighted and used this as my threshold value. This effectively completed my objective.
Here is my code.
import cv2
import numpy as np
# Only for the threshold display
from matplotlib import pyplot as plt
# The Image to be used
image = 'DepthMap.png'
# Finding the average greyscale value
image_bgr = cv2.imread(image, cv2.IMREAD_GRAYSCALE)
# Calculate the mean of each channel
channels = cv2.mean(image_bgr)
# Type Float
thresh = channels[0]/2
#print (thresh)
# Displaying the threshold value
img = cv2.imread(image,0)
img = cv2.medianBlur(img,5)
# If below then black else white
ret,th1 = cv2.threshold(img,thresh,255,cv2.THRESH_BINARY)
titles = ['Original Image', 'Global Thresholding']
images = [img, th1]
for i in range(2):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
# Shows single image on its' own
'''
plt.imshow(images[1], 'gray')
plt.xticks([]),plt.yticks([])
'''
plt.show()
DepthMap.png:
Output:
To prove that this works on other images I also tested the same code on another Depth Map:
Input:
Output:
Evaluation Although you can see in both images the darkest value is different, the algorithm has adapted and still works, this means that this could be used on video depth maps also and not require constant tweaking.
来源:https://stackoverflow.com/questions/65553353/how-to-mask-a-depth-map-to-select-darkest-values-in-image