Я использую определение цвета (в частности, фиолетового) и определение круга, чтобы обнаружить объект пыльцы (фиолетовый круговой) на изображении ниже.
Затем я пишу букву "P" в обнаруженном объекте. К сожалению, это не сработало, как я ожидал.
Я могу исправить это, если изменить радиус, но это не очень хорошая идея, так как у меня все еще есть много похожих изображений с различным радиусом для обработки. я думаю, что основной момент - узнать, как точно этот диапазон пурпурного изображения. Как правило, я хочу знать, как получить диапазон произвольного цвета в изображении. Некоторые люди дали мне пример кода, но это не сработало.
Вот моя программа.
import cv2
import numpy as np
# In[2]:
path = "./sample.JPG"
font = cv2.FONT_HERSHEY_COMPLEX
# In[3]:
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
# In[4]:
iml = cv2.imread(path,cv2.IMREAD_COLOR)
img = image_resize(iml,width=960)
# In[5]:
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hsv = cv2.medianBlur(hsv,5)
#mask = cv2.inRange(hsv, (120, 180, 50), (160, 255, 255))
mask = cv2.inRange(hsv, (105, 100,50), (160, 255, 255))
#mask = cv2.inRange(hsv, (126, 142, 57), (145, 255, 255))
#cv2.GaussianBlur(cimg, (9,9),3)
#cimg = cv2.medianBlur(cimg,5)
output = cv2.bitwise_and(hsv, hsv, mask = mask)
#circles = cv2.HoughCircles(mask[:,:,0],cv2.HOUGH_GRADIENT,1,mask.shape[0]/16,param1=15,param2=20,minRadius=18,maxRadius=38)
circles = cv2.HoughCircles(output[:,:,0],cv2.HOUGH_GRADIENT,1,output.shape[0]/16,param1=15,param2=20,minRadius=15,maxRadius=30)
print(len(circles))
circles = np.uint16(np.around(circles))[0,:]
# In[6]:
for i in circles:
cv2.putText(img,'P',(i[0],i[1]), font, 0.5,(0,255,0),1,cv2.LINE_AA)
# In[7]:
cv2.imwrite("./result.jpg",img)
Обратите внимание, что этот ответ не предназначен для решения, но может быть, новой точки зрения для достижения вашей задачи. Несмотря на то, что он может работать в некоторых случаях, он, вероятно, не будет достаточно прочным для автоматизации любых процессов. При этом проблема с преобразованием в цветовое пространство HSV заключается в том, что если изображение (как и в вашем случае) имеет похожие на него объекты цвета, то будет сложно выделить один объект из другого с помощью cv2.inRange()
. Я попытался немного изменить код и сделал пример того, как я подойду к этому.
Сначала вы можете попытаться найти все контуры после порога OTSU на изображении и отфильтровать самые большие (пончики) и другие маленькие с критериями по вашему выбору.
После этого вы можете сделать ROI вокруг этого контура. Затем я попытался выполнить cv2.inRange()
для каждого ROI.
После этого я бы снова искал контуры для каждого ROI и подсчитывал белые пиксели или делал критерии округления для контуров. Если они пройдут, это означает, что у него много пикселей в диапазоне и нарисуйте букву Т. Надеюсь, что это немного помогает. Ура!
Пример:
import cv2
import numpy as np
# In[2]:
path = "./purplecirc4.JPG"
font = cv2.FONT_HERSHEY_COMPLEX
# In[3]:
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
# In[4]:
iml = cv2.imread(path,cv2.IMREAD_COLOR)
img = image_resize(iml,width=960)
# Threshold with OTSU to get all contours
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)
_,thresh = cv2.threshold(blur,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# Empty list for contours that could be positive
ROIs=[]
# Append possible contours to list
# (I have selected height to eliminate unwanted noise)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
if 200 > h > 20:
x1 = x-20
x2 = x+w+20
y1 = y-20
y2 = y+h+20
roi = img[y1:y2, x1:x2]
ROIs.append(roi)
# Iterate through list of ROIS and transform to HSV
# (I made a little adjustment in values )
for i in ROIs:
hsv = cv2.cvtColor(i,cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (115,100,50), (160,255,255))
# Search for contours on every ROI in list and select the biggest one
_, contours, hierarchy = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
# Draw them whole on hsv then transform to gray and perform OTSU threshold and search for contoures
cv2.drawContours(hsv, [cnt], 0, 255, -1)
gray = cv2.cvtColor(hsv, cv2.COLOR_BGR2GRAY)
_,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
# Make a "roundness" criterion and draw the letter
x,y,w,h = cv2.boundingRect(cnt)
perimeter = cv2.arcLength(cnt,True)
radius = perimeter/(2*np.pi)
area = cv2.contourArea(cnt)
circ = 4*area/(np.pi*(radius*2)**2)
if circ > 0.70:
cv2.putText(i,'P',(int(x+(w/2.5)),int(y+(h/2))), font, 0.5,(0,255,0),1,cv2.LINE_AA)
# Display result:
resized = cv2.resize(img, (0,0), fx=0.5, fy=0.5)
cv2.imshow("roi",resized)
cv2.waitKey(0)
cv2.destroyAllWindows()
Результат: