如何在Python中使用分水岭算法分离图像

如何在Python中使用分水岭算法分离图像,python,opencv,image-processing,computer-vision,data-science,Python,Opencv,Image Processing,Computer Vision,Data Science,如何利用Python中的分水岭算法在图像分割后的多幅图像中分离单个图像 附加的图像由4幅图像组成,我们需要从中应用图像分割,并将单个图像从这4幅图像中分离出来 我们将先用洪水填满它 导入cv2; 输入numpy作为np; #读取图像 im_in=cv2.imread(“2SNAT.jpg”,cv2.imread_灰度); #门槛。 #将等于或高于220的值设置为0。 #将值设置为220到255以下。 th,im_th=cv2.阈值(im_in,220,255,cv2.阈值二进制\u INV);

如何利用Python中的分水岭算法在图像分割后的多幅图像中分离单个图像 附加的图像由4幅图像组成,我们需要从中应用图像分割,并将单个图像从这4幅图像中分离出来

我们将先用洪水填满它

导入cv2;
输入numpy作为np;
#读取图像
im_in=cv2.imread(“2SNAT.jpg”,cv2.imread_灰度);
#门槛。
#将等于或高于220的值设置为0。
#将值设置为220到255以下。
th,im_th=cv2.阈值(im_in,220,255,cv2.阈值二进制\u INV);
#复制阈值图像。
im_floodfill=im_th.copy()
#用于填充洪水的面罩。
#请注意,大小需要比图像大2个像素。
h、 w=中间形状[:2]
掩码=np.0((h+2,w+2),np.uint8)
#从点(0,0)开始的洪水填充
cv2.泛光填充(im_泛光填充,遮罩,(0,0),255);
#反转泛光图像
im\U泛光填充\U inv=cv2。按位\U not(im\U泛光填充)
#将这两幅图像合并以获得前景。
im_out=im|th | im_floodfill_inv

然后找到轮廓并裁剪出来

im,轮廓,层次=cv2.findContours(im\u out.copy(),cv2.RETR\u EXTERNAL,cv2.CHAIN\u近似值\u NONE)
最终_等高线=[]
对于等高线中的等高线:
面积=cv2。轮廓面积(轮廓)
如果面积>1000:
最终轮廓。附加(轮廓)
裁剪步骤,同时在原始图像上绘制矩形

计数器=0
对于最终轮廓中的c:
计数器=计数器+1
#对于[final_等高线[0]]中的c:
peri=cv2.弧长(c,真)
近似值=cv2.近似聚合度(c,0.01*peri,真)
x、 y,w,h=cv2.边界矩形(近似值)
打印(x、y、w、h)
纵横比=宽/浮点数(h)

如果(纵横比>=0.8,纵横比而不是使用分水岭,这里有一个使用阈值+形态学操作的简单方法。其思想是获得一个二值图像,然后执行变形接近,将每个对象合并为一个轮廓。然后,我们使用Numpy切片查找轮廓并提取/保存每个ROI

下面是以绿色高亮显示的每个单独对象

单个保存的对象

代码


我认为分水岭不适用于这种情况。请你提供建议,如何解决这个问题。@Ashish我不是这方面的专家,所以我的方法可能不是最好的,如果你需要更多的解释,请发表评论,你说对了,伙计。我们快找到解决办法了。只是收到以下错误消息:------------------------------------------------------------------------------>1等高线中的TypeError Traceback(最近一次调用last),hierarchy=cv2.findContours(cv2.RETR\u EXTERNAL,cv2.CHAIN\u About\u NONE)2 3最终等高线=[]4等高线中的等高线:5 area=cv2。等高线区域(等高线)TypeError:findContours()缺少所需的参数“方法”(位置3)感谢Buddy的快速帮助和响应,也来自第一块代码的输出图像,是否可以仅从第一张图中单独获取单独的图像,就像实际需要的四个黄色阴影图像一样(不带正方形边界)在中,行尾的分号不是必需的Python@Ashish您使用的
findContours
代码行缺少图像输入的第一个参数,
im,contours,hierarchy=cv2.findContours(im\u out.copy(),cv2.RETR\u EXTERNAL,cv2.CHAIN\u APPROX\u NONE)
此外,如果要获取黄色阴影图像,请更改此行(裁剪并写入文件)
cv2.imwrite('splitted{}.jpg'.格式(计数器),im_in[y:y+h,x:x+w])
to
cv2.imwrite('splitted{}.jpg'.格式(计数器),im_out[y:y+h,x:x+w])
谢谢@Nathance。上面的逻辑不适用于未正确对齐的图像。您能建议如何处理图像,以便图像中有两个单独的图像A和B,我已经在图像中描述过。提前感谢如果它不是矩形对象,您必须使用位掩蔽。找到轮廓并绘制每个轮廓浏览白色的空白蒙版,然后按位和原始输入。从这里找到蒙版上的边界框并提取ROI
import cv2

# Load image, grayscale, Otsu's threshold
image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Morph close
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=3)

# Find contours and extract ROI
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
num = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite('ROI_{}.png'.format(num), ROI)
    num += 1

cv2.imshow('image', image)
cv2.waitKey()