如何用Python中openCV轮廓区域指定的颜色填充openCV轮廓?

如何用Python中openCV轮廓区域指定的颜色填充openCV轮廓?,python,opencv,image-processing,image-segmentation,Python,Opencv,Image Processing,Image Segmentation,我对生物细胞进行了分割和二元化,并使用openCV提取了轮廓的区域和周长。我试图根据参数q=周长/Sqrt(面积)使用颜色映射对每个单元格进行标记和着色,但我甚至不知道从哪里开始。根据该值,每个单元格基本上都有一个唯一的颜色 任何帮助都将不胜感激!以下是我到目前为止的情况: > #specify folders filelocat = '/Users/kate/Desktop/SegmenterTest3/SegmentedCells/' #process image img = cv2

我对生物细胞进行了分割和二元化,并使用openCV提取了轮廓的区域和周长。我试图根据参数q=周长/Sqrt(面积)使用颜色映射对每个单元格进行标记和着色,但我甚至不知道从哪里开始。根据该值,每个单元格基本上都有一个唯一的颜色

任何帮助都将不胜感激!以下是我到目前为止的情况:

> #specify folders
filelocat = '/Users/kate/Desktop/SegmenterTest3/SegmentedCells/'

#process image
img = cv2.imread(str(filelocat) + 'Seg3.png')
image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(image, 60, 255, cv2.THRESH_BINARY)[1]
kernel = np.ones((20,20), np.uint8)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
#inverts image so that the objects are white (for analysis)
imagem = cv2.bitwise_not(closing)

#Find contours
cnts = cv2.findContours(imagem.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

#calculate moments and extract cell shape info
moment_dict = {}
for index, cnt in enumerate(cnts):
    moment_dict[index] = cv2.moments(cnt)
    
obj_properties = {}
for index, (key, obj_moments) in enumerate(moment_dict.items()):
    if obj_moments['m00'] > 1000 and obj_moments['m00'] < 20000:
        area = obj_moments['m00']
        cx = obj_moments['m10'] / obj_moments['m00']
        cy = obj_moments['m01'] / obj_moments['m00']
        peri = cv2.arcLength(cnts[index], True)
        q = (peri/(math.sqrt(area)))
        props = {}
        props['q']=q
        props['peri']=peri
        props['area']=area
        props['cx']=cx
        props['cy']=cy
        obj_properties[key] = props
#指定文件夹
filelocat='/Users/kate/Desktop/SegmenterTest3/SegmentedCells/'
#处理图像
img=cv2.imread(str(filelocat)+'Seg3.png')
图像=cv2.CVT颜色(img,cv2.COLOR\u BGR2GRAY)
thresh=cv2.threshold(图像,60255,cv2.thresh_二进制)[1]
kernel=np.one((20,20),np.uint8)
closing=cv2.morphologyEx(thresh,cv2.MORPH\u CLOSE,kernel)
#反转图像,使对象为白色(用于分析)
imagem=cv2。按位\u非(关闭)
#寻找轮廓
cnts=cv2.findContours(imagem.copy(),cv2.RETR\u LIST,cv2.CHAIN\u近似值\u SIMPLE)
cnts=imutils.GRAP_轮廓(cnts)
#计算矩并提取单元形状信息
力矩_dict={}
对于索引,枚举中的cnt(cnt):
力矩[index]=cv2.力矩(cnt)
obj_属性={}
对于枚举(矩dict.items())中的索引(键,对象矩):
如果obj_矩['m00']>1000且obj_矩['m00']<20000:
面积=obj_力矩['m00']
cx=obj_矩['m10']/obj_矩['m00']
cy=obj_矩['m01']/obj_矩['m00']
peri=cv2.弧长(cnts[指数],真)
q=(周长/(数学sqrt(面积)))
道具={}
道具['q']=q
道具['peri']=peri
道具['area']=面积
道具['cx']=cx
道具['cy']=cy
obj_属性[键]=道具

谢谢你的帮助

要解决这个问题,您需要收集所有的q值,以便根据观察到的q值范围对它们进行缩放。您可以使用如下列表来完成此操作:

obj\u properties.items()中k的所有\u q=[v['q'],v

您还需要选择一些颜色贴图。根据前面评论中的建议,我将此作为读者的练习。简单来说,只要将q值缩放到8位RGB,就可以看到初步结果

请参阅下面的完整代码。请注意,
时刻表中的
索引
对象属性
字典中的键,因此整个
枚举
构造是不必要的。我冒昧地把
enumerate
全部删除了。无论如何,过滤循环都会拾取正确的轮廓索引。根据标准选择轮廓后,收集所有q并计算其最小/最大/范围。然后用这些来衡量个人的q的任何规模你需要。在下面的示例中,我将其缩放为绿色组件的8位值。你可以根据自己的意愿选择红色和蓝色

请注意,在这张图中,大多数q值在4.0-4.25范围内,少数异常值在5.50(绘制直方图以查看该分布)。这会使颜色贴图倾斜,因此大多数单元格的颜色都非常相似。然而,我希望这能帮助你开始。我建议对q应用对数函数,以便直观地“展开”其分布的低端

  • 编辑:用matplotlib中的颜色贴图替换了基本颜色贴图。有关所有可能的颜色贴图选项,请参阅
导入matplotlib.pyplot作为plt
输入数学
导入操作系统
进口cv2
导入imutils
将numpy作为np导入
#指定文件夹
filelocat='/Users/kate/Desktop/SegmenterTest3/SegmentedCells/'
#处理图像
img=cv2.imread(os.path.join(filelocat,'Seg3.png'))
图像=cv2.CVT颜色(img,cv2.COLOR\u BGR2GRAY)
thresh=cv2.threshold(图像,60255,cv2.thresh_二进制)[1]
内核=np.ones((20,20),np.uint8)
closing=cv2.morphologyEx(thresh,cv2.MORPH\u CLOSE,kernel)
#反转图像,使对象为白色(用于分析)
imagem=cv2。按位\u非(关闭)
#寻找轮廓
cnts=cv2.findContours(imagem.copy(),cv2.RETR\u LIST,cv2.CHAIN\u近似值\u SIMPLE)
cnts=imutils.GRAP_轮廓(cnts)
#计算矩并提取单元形状信息
力矩_dict={}
对于索引,枚举中的cnt(cnt):
力矩[index]=cv2.力矩(cnt)
obj_属性={}
对于索引,矩量表项()中的对象矩:
如果obj_矩['m00']>1000且obj_矩['m00']<20000:
面积=obj_力矩['m00']
cx=obj_矩['m10']/obj_矩['m00']
cy=obj_矩['m01']/obj_矩['m00']
peri=cv2.弧长(cnts[指数],真)
q=(周长/(数学sqrt(面积)))
道具={}
道具['q']=q
道具['peri']=peri
道具['area']=面积
道具['cx']=cx
道具['cy']=cy
obj_属性[索引]=道具
obj_properties.items()中k和v的所有_q=[v['q']
最小值=最小值(所有值)
max_q=max(全部)
范围=最大值-最小值
#q标量到BGR值的颜色映射
cmap=plt.cm.get_cmap(“地形”)
对于索引,在obj_properties.items()中使用prop:
v=(道具['q']-min_q)/range_q
r、 g,b,a=[int(x)表示cmap中的x(v,bytes=True)]
cv2.拉伸轮廓(img,CNT,指数,(b,g,r),-1)
cv2.imwrite('colored.png',img)
cv2.imshow(“生物细胞”,img)
cv2.等待键(10000)

颜色可以是随机的,还是必须是唯一的颜色列表?理想情况下,我希望使用颜色贴图来表示值的渐变,但任何颜色贴图都可以!若要使用特定的颜色贴图,您必须根据不同的区域定义尽可能多的颜色,绘制轮廓时必须知道这些颜色。在谷歌搜索
python opencv draw random colors
。你会找到答案,比如用随机颜色绘制的和。哇,这太棒了!非常感谢。我已经成功地将其应用到了细胞上,并对它们进行了很好的标记。现在我想弄清楚如何移除外部细胞
import matplotlib.pyplot as plt
import math
import os
import cv2
import imutils
import numpy as np
# specify folders
filelocat = '/Users/kate/Desktop/SegmenterTest3/SegmentedCells/'

# process image
img = cv2.imread(os.path.join(filelocat, 'Seg3.png'))
image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(image, 60, 255, cv2.THRESH_BINARY)[1]
kernel = np.ones((20, 20), np.uint8)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# inverts image so that the objects are white (for analysis)
imagem = cv2.bitwise_not(closing)

# Find contours
cnts = cv2.findContours(imagem.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

# calculate moments and extract cell shape info
moment_dict = {}
for index, cnt in enumerate(cnts):
    moment_dict[index] = cv2.moments(cnt)

obj_properties = {}
for index, obj_moments in moment_dict.items():
    if obj_moments['m00'] > 1000 and obj_moments['m00'] < 20000:
        area = obj_moments['m00']
        cx = obj_moments['m10'] / obj_moments['m00']
        cy = obj_moments['m01'] / obj_moments['m00']
        peri = cv2.arcLength(cnts[index], True)
        q = (peri/(math.sqrt(area)))
        props = {}
        props['q'] = q
        props['peri'] = peri
        props['area'] = area
        props['cx'] = cx
        props['cy'] = cy
        obj_properties[index] = props

all_the_q = [v['q'] for k, v in obj_properties.items()]
min_q = min(all_the_q)
max_q = max(all_the_q)
range_q = max_q - min_q

# colormapping of q scalars to BGR values
cmap = plt.cm.get_cmap('terrain')
for index, prop in obj_properties.items():
    v = (prop['q'] - min_q) / range_q
    r, g, b, a = [int(x) for x in cmap(v, bytes=True)]
    cv2.drawContours(img, cnts, index, (b, g, r), -1)

cv2.imwrite('colored.png', img)
cv2.imshow('Biocells', img)
cv2.waitKey(10000)