如何使用opencv和python分割属于生物样本的图像内的相似外观区域(明智的选择)? [英] How to segment similar looking areas (color wise) inside a image that belong to biosamples with opencv and python?

查看:62
本文介绍了如何使用opencv和python分割属于生物样本的图像内的相似外观区域(明智的选择)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试分析假单胞菌生物膜的图像,我这样做是为了找到其生长与分布之间具有某种自变量的某种相关性.我已经应用了分割以获得感兴趣的圆形区域,现在我正在考虑将某些颜色分割应用到具有HSV值的图像上,从而仅使区域具有生物膜.我试图以某种方式完全隔离所有重要区域,我对图像应用了bitwise_not来查看负片,并发现在视觉上更容易区分,所有淡黄色的区域都带有细菌它.

原始图片:

否定:

使用我编写的代码,我必须对细菌的大斑点进行分割,但并不是真正分离出所有细菌的区域.

  import cv2将numpy导入为np导入操作系统def color_segmentation(image):hsv = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)mask1 = cv2.inRange(hsv,(90,90,50),(179,255,160))target = cv2.bitwise_and(image,image,mask = mask1)返回目标测试= cv2.imread(路径)结果= color_segmentation(测试)cv2.imshow('结果',结果) 

我已经知道该代码非常简单,因此当我无法隔离所有感兴趣的区域时,这并不令我感到惊讶,您是否认为如果应用更多的蒙版,我可以提取所有泛黄的区域吗?也许有人会说某种算法与我正在寻找的算法有些相似.预先感谢任何有兴趣的人.

结果:

解决方案

一个想法是执行Kmeans颜色量化,以将图像聚类为不同数量的颜色.之后,我们可以使用

  [67.70980019 86.19251507 121.19410086] 0.87%[120.61108133 146.00169267 159.48142297] 9.78%[0.18113609 0.22505063 0.25559479] 21.40%[134.06236381 170.04397205 167.3696234] 23.44%[140.53640479 189.4275781 171.19319177] 44.50% 

接下来,我们将执行颜色阈值处理以获得具有此较低/较高颜色范围的蒙版

  lower = np.array([84,0,0])upper = np.array([179,255,255]) 

我们将蒙版应用于原始图像以获得结果

还记得我们用来确定是否存在细菌的三种颜色分布吗?如果更改颜色阈值范围,则可以将图像进一步分为细菌的大,中和小区域.

使用此颜色范围,我们只能分离出较大的细菌区域

  lower = np.array([104,0,0])upper = np.array([179,255,255]) 

蒙版-> 结果

对于中等地区

  lower = np.array([90,0,0])upper = np.array([102,255,255]) 

最后,获得小区域

  lower = np.array([84,0,0])upper = np.array([98,255,255]) 

代码

  import cv2将numpy导入为np#Kmeans颜色分割def kmeans_color_quantization(图像,簇数= 8,回合= 1):h,w = image.shape [:2]样本= np.zeros([h * w,3],dtype = np.float32)计数= 0对于x在范围(h)中:对于范围(w)中的y:样本[数量] =图片[x] [y]计数+ = 1紧密度,标签,中心= cv2.kmeans(样本,集群没有任何,(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,10000,0.0001),回合cv2.KMEANS_RANDOM_CENTERS)中心= np.uint8(中心)res =中心[labels.flatten()]返回res.reshape((image.shape))#加载原始图像原始= cv2.imread('2.png')#执行kmeans颜色分割kmeans = kmeans_color_quantization(原始,簇= 5)#kmeans图像上的颜色阈值hsv = cv2.cvtColor(kmeans,cv2.COLOR_BGR2HSV)较低= np.array([84,0,0])upper = np.array([179,255,255])遮罩= cv2.inRange(hsv,下,上)#将蒙版应用到原始图像上结果= cv2.bitwise_and(原始,原始,遮罩=遮罩)result [mask == 0] =(255,255,255)# 展示cv2.imshow('kmeans',kmeans)cv2.imshow('结果',结果)cv2.imshow('遮罩',遮罩)cv2.waitKey() 

此HSV颜色阈值脚本用于确定较低/较高的颜色范围

  import cv2将numpy导入为npdef none(x):经过#加载图片图片= cv2.imread('1.png')#创建一个窗口cv2.namedWindow('image')#创建用于更改颜色的跟踪栏#OpenCv的色相介于0-179之间cv2.createTrackbar('HMin','image',0,179,没什么)cv2.createTrackbar('SMin','image',0,255,没什么)cv2.createTrackbar('VMin','image',0,255,没什么)cv2.createTrackbar('HMax','image',0,179,没什么)cv2.createTrackbar('SMax','image',0,255,没什么)cv2.createTrackbar('VMax','image',0,255,没什么)#设置Max HSV跟踪栏的默认值cv2.setTrackbarPos('HMax','image',179)cv2.setTrackbarPos('SMax','image',255)cv2.setTrackbarPos('VMax','image',255)#初始化HSV最小值/最大值hMin = sMin = vMin = hMax = sMax = vMax = 0phMin = psMin = pvMin = phMax = psMax = pvMax = 0while(1):#获取所有轨迹栏的当前位置hMin = cv2.getTrackbarPos('HMin','image')sMin = cv2.getTrackbarPos('SMin','image')vMin = cv2.getTrackbarPos('VMin','image')hMax = cv2.getTrackbarPos('HMax','image')sMax = cv2.getTrackbarPos('SMax','image')vMax = cv2.getTrackbarPos('VMax','image')#设置要显示的最小和最大HSV值较低= np.array([hMin,sMin,vMin])upper = np.array([hMax,sMax,vMax])#转换为HSV格式和颜色阈值hsv = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)遮罩= cv2.inRange(hsv,下,上)结果= cv2.bitwise_and(图像,图像,遮罩=遮罩)#打印HSV值是否有变化if((phMin!= hMin)|(psMin!= sMin)|(pvMin!= vMin)|(phMax!= hMax)|(psMax!= sMax)|(pvMax!= vMax)):print((hMin =%d,sMin =%d,vMin =%d),(hMax =%d,sMax =%d,vMax =%d)"%(hMin,sMin,vMin,hMax,sMax,vMax))phMin = hMinpsMin = sMinpvMin = vMinphMax = hMaxpsMax = sMaxpvMax = vMax#显示结果图像cv2.imshow('image',结果)如果cv2.waitKey(10)&0xFF == ord('q'):休息cv2.destroyAllWindows() 

I'm trying to analyze images of bio-films of pseudomona, I'm doing this in order to find some kind of correlation between its grow and distribution with some independent variables. I've applied a segmentation to obtain a circular area of interest and now I was thinking in applying some color segmentation to the image with its HSV values to just leave the areas with bio-film. I've trying to think in a way to completely isolate all the areas that are important, I applied a bitwise_not to the image to see the negative and have found that is visually more easy to distinguish, all the areas that are yellowish have bacteria on it.

Original image:

Negative:

With the code I've written, I've got to segment big spots of the bacteria, but not all the areas that really have it.

import cv2
import numpy as np
import os
def color_segmentation(image):
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask1 = cv2.inRange(hsv, (90,90,50), (179,255,160))
    target = cv2.bitwise_and(image, image, mask=mask1)
    return target
test = cv2.imread(path)
result = color_segmentation(test)
cv2.imshow('result', result)

I already know that the code it's really simple, so it didn't surprise me when I couldn't isolate all the areas of interest, do you think that if apply more masks could I extract all the yellowish areas? Or maybe someone could say an algorithm that's somewhat similar to what I'm looking. Thanks in advance to anyone interested.

Result:

解决方案

One idea is to perform Kmeans color quantization to cluster the image into a distinct amount of colors. Afterwards, we can convert the image to HSV format and perform color thresholding using cv2.inRange with a lower/upper color threshold to obtain a binary mask. Finally we apply this mask onto the original image using cv2.bitwise_and.


Original image -> Kmeans color quantization with clusters=5

Notice the subtle difference in that the entire image is segmented into five colors. Here's a visualization of each color cluster and the color distribution percentage. Based on the color segmentation, we can estimate that the first three colors (ignoring black) have bacteria on it.

[ 67.70980019  86.19251507 121.19410086] 0.87%
[120.61108133 146.00169267 159.48142297] 9.78%
[0.18113609 0.22505063 0.25559479] 21.40%
[134.06236381 170.04397205 167.3696234 ] 23.44%
[140.53640479 189.4275781  171.19319177] 44.50%

Next we perform color thresholding to obtain a mask with this lower/upper color range

lower = np.array([84, 0, 0])
upper = np.array([179, 255, 255])

We apply the mask onto the original image to get our result

Remember how there were three color distributions we used to determine if there was bacteria? If we change the color threshold range, we can further segment the image into large, medium, and small regions of bacteria.

We can isolate only the large bacteria regions using this color range

lower = np.array([104, 0, 0])
upper = np.array([179, 255, 255])

Mask -> Result

For the medium regions

lower = np.array([90, 0, 0])
upper = np.array([102, 255, 255])

Finally, to obtain the small regions

lower = np.array([84, 0, 0])
upper = np.array([98, 255, 255])

Code

import cv2
import numpy as np

# Kmeans color segmentation
def kmeans_color_quantization(image, clusters=8, rounds=1):
    h, w = image.shape[:2]
    samples = np.zeros([h*w,3], dtype=np.float32)
    count = 0

    for x in range(h):
        for y in range(w):
            samples[count] = image[x][y]
            count += 1

    compactness, labels, centers = cv2.kmeans(samples,
            clusters, 
            None,
            (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001), 
            rounds, 
            cv2.KMEANS_RANDOM_CENTERS)

    centers = np.uint8(centers)
    res = centers[labels.flatten()]
    return res.reshape((image.shape))

# Load original image
original = cv2.imread('2.png')

# Perform kmeans color segmentation
kmeans = kmeans_color_quantization(original, clusters=5)

# Color threshold on kmeans image
hsv = cv2.cvtColor(kmeans, cv2.COLOR_BGR2HSV)
lower = np.array([84, 0, 0])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)

# Apply mask onto original image
result = cv2.bitwise_and(original, original, mask=mask)
result[mask==0] = (255,255,255)

# Display
cv2.imshow('kmeans', kmeans)
cv2.imshow('result', result)
cv2.imshow('mask', mask)
cv2.waitKey()

This HSV color thresholder script was used to determine the lower/upper color ranges

import cv2
import numpy as np

def nothing(x):
    pass

# Load image
image = cv2.imread('1.png')

# Create a window
cv2.namedWindow('image')

# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)

# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

while(1):
    # Get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin', 'image')
    sMin = cv2.getTrackbarPos('SMin', 'image')
    vMin = cv2.getTrackbarPos('VMin', 'image')
    hMax = cv2.getTrackbarPos('HMax', 'image')
    sMax = cv2.getTrackbarPos('SMax', 'image')
    vMax = cv2.getTrackbarPos('VMax', 'image')

    # Set minimum and maximum HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Convert to HSV format and color threshold
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    result = cv2.bitwise_and(image, image, mask=mask)

    # Print if there is a change in HSV value
    if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
        print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax

    # Display result image
    cv2.imshow('image', result)
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

这篇关于如何使用opencv和python分割属于生物样本的图像内的相似外观区域(明智的选择)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆