细胞识别与分类

前言#

细胞图片数据如下

细胞识别#

要想对图片中细胞进行分类,首先就要将图片中的细胞识别出来
首先读入图片,接着转化为灰度图,接着对图片进行高斯模糊化处理,接着采用自适应的阀值将图片转化为二值图像,接着定义椭圆形的核对图像进行先腐蚀后膨胀的操作,用于处理噪声。
效果图如下:
灰度图像

阀值处理为二值图像

腐蚀膨胀去噪后图像

但是依然有一些噪点,所以计算其连通部分,对每一个连通部分计算其像素数量,过滤掉小于100像素的部分
效果图如下:
连通部分展示,不同颜色代表不同连通部分

去像素数量小于100的连通部分后效果如图所示

之后寻找每个连通部分边界,用圆形标记每个部分边界
效果图如下:
每一个圆圈表示识别的一个细胞

但是有一些相邻的细胞被识别成一个,这时我尝试了很多办法,如:重新对图片进行清洗,计算其前景后景,从而运用分水岭算法等都没有 获得很好的提升,所以只能将暂时放弃,之后将这些异常的数据丢弃。

细胞分类#

识别细胞后,要进行分类,因为对分类依据并不了解,所以之间识别细胞的颜色和细胞的大小作为分类的特征。采用Kmeans自聚类的方法对细胞进行分类
细胞颜色采用标记区域内颜色的均值,细胞大小采用标记区域的面积
提取细胞数据如图所示,横轴表示细胞面积,竖轴表示细胞的颜色。但是在图中可以看出有三个面积异常大的值,正好就是之前标记细胞出错的位置,所以暂时去除这三个值:

去除三个异常值后如图所示

最后通过Kmeans算法进行自聚类,分为两类,并在原图上进行标记
分类效果如下所示

在图像上进行标记效果,其中标有红点为一类,标有蓝点为一类

完整代码如下所示:#

Copy
import cv2 import numpy as np from skimage import measure,color import collections import matplotlib.pyplot as plt from sklearn.cluster import KMeans image_orign=cv2.imread(r'C:\Users\DELL\Desktop\1.jpg') gray = cv2.cvtColor(image_orign,cv2.COLOR_BGR2GRAY) blurred=cv2.GaussianBlur(gray,(11,11),0) thresh=cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 11, 2) kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) erode_img=cv2.erode(thresh,kernel,iterations=1)#腐蚀 dilate_img=cv2.dilate(erode_img,kernel,iterations=1)#膨胀 #分水岭算法 # sure_bg=cv2.dilate(dilate_img,kernel,iterations=3)#膨胀 # cv2.imshow('t',sure_bg) # cv2.waitKey(0) # dist_transform=cv2.distanceTransform(dilate_img,cv2.DIST_L2,5) # ret ,sure_fg=cv2.threshold(dist_transform,0.55*dist_transform.max(),255,0) # cv2.imshow('t',sure_fg) # cv2.waitKey(0) # sure_fg = np.uint8(sure_fg) # unknow=cv2.subtract(sure_bg,sure_fg) # ret2,makers=cv2.connectedComponents(sure_fg) # markers=makers+1 # markers[unknow==0]=255 # markers=cv2.watershed(image_orign,markers) # dilate_img[markers == 255] =0 # cv2.imshow('t',dilate_img) # cv2.waitKey(0) labels=measure.label(dilate_img,connectivity=2,background=1) dst=color.label2rgb(labels) image=np.zeros(dilate_img.shape,dtype='uint8') cell_color=[] for label in collections.Counter(np.unique(labels)).keys(): if(label==1): continue mask=np.zeros(dilate_img.shape,dtype='uint8') mask[labels==label]=255 num_pixel=cv2.countNonZero(mask) if(num_pixel>100): image=cv2.add(image,mask) cell_set=[] cell_size=[] cont,hierarchy=cv2.findContours(image.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) for i in cont: x,y,w,h=cv2.boundingRect(i) (cx,cy),radius=cv2.minEnclosingCircle(i) cv2.circle(image_orign,(int(cx),int(cy)),int(radius),(0,0,0),3) cell_set.append((int(cx),int(cy))) cell_size.append(np.pi*radius*radius/10) roi=np.zeros(gray.shape,dtype='uint8') roi = cv2.circle(roi, (int(cx),int(cy)), int(radius), 255, cv2.FILLED) mask2=np.ones(gray.shape,dtype='uint8')*255 area=cv2.bitwise_and(mask2, gray, mask=roi) cell_color.append(area.sum()/cv2.countNonZero(area)) value=[] d=cell_size.copy() d.sort() for i in d[len(d)-3:]: cell_set.pop(cell_size.index(i)) cell_color.pop(cell_size.index(i)) cell_size.remove(i) for i in range(len(cell_set)): value.append([cell_size[i],cell_color[i]]) data=dict(zip(cell_set,value)) plt.scatter(cell_size,cell_color) plt.show() pre=KMeans(n_clusters=2).fit_predict(value) c=[(255,0,0),(0,0,255)] c2=['red','blue'] for i in range(len(list(pre))): plt.scatter(value[i][0],value[i][1],c=c2[pre[i]]) cv2.circle(image_orign,(cell_set[i][0],cell_set[i][1]),3,c[pre[i]],cv2.FILLED) cv2.imshow('t',image_orign) cv2.waitKey(0) plt.show()
posted @   启林O_o  阅读(693)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示
CONTENTS