Image segmentation in python

雨燕双飞 提交于 2021-02-07 08:00:33

问题


I have the image shape image

I am looking for python solution to break the shape in this image into smaller parts according to the contour in the image.

I have looked into solution on Canny and findContours in OpenCV but none of them works for me.

Edit:

Code used:

using Canny method

import cv2 import numpy as np

img = cv2.imread('area_of_blob_maxcontrast_white.jpg') edges = cv2.Canny(img, 100, 200)
cv2.imwrite('area_of_blob_maxcontrast_white_edges.jpg',edges)

using findContours method

import numpy as np 
import argparse 
import cv2

image = cv2.imread('area_of_blob_maxcontrast_white.png')

lower = np.array([0, 0, 0]) upper = np.array([15, 15, 15]) shapeMask = cv2.inRange(image, lower, upper)

(_,cnts, _) = cv2.findContours(shapeMask.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE) print "I found %d black shapes" % (len(cnts)) cv2.imshow("Mask", shapeMask)

for c in cnts:
    # draw the contour and show it
    cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
    cv2.imshow("Image", image)
    cv2.waitKey(0)

回答1:


The trick is to make your faint single pixel boundary slightly bolder. I do it by changing any white pixel that has two adjacent black pixels (above, below, to the left or to the right) to black. (I do it extremely slow, though. I'm pretty sure there must be a smarter way to do it with OpenCV or Numpy.)

Here is my code:

#!/usr/bin/env python 

import numpy as np
import cv2

THRESH = 240

orig = cv2.imread("map.png")
img = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)

# Make the faint 1-pixel boundary bolder
rows, cols = img.shape
new_img = np.full_like(img, 255)    # pure white image
for y in range(rows):
    if not (y % 10):
        print ('Row = %d (%.2f%%)' % (y, 100.*y/rows))
    for x in range(cols):
        score  = 1 if y > 0 and img.item(y-1, x) < THRESH else 0
        score += 1 if x > 0 and img.item(y, x-1) < THRESH else 0
        score += 1 if y < rows-1 and img.item(y+1, x) < THRESH else 0
        score += 1 if x < cols-1 and img.item(y, x+1) < THRESH else 0
        if img.item(y, x) < THRESH or score >= 2:
            new_img[y, x] = 0       # black pixels show boundary

cv2.imwrite('thresh.png', new_img)

# Find all contours on the map
_th, contours, hierarchy = cv2.findContours(new_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
print "Number of contours detected = %d" % len(contours)

# Fill second level regions on the map
coln = 0
colors = [
    [127, 0, 255],
    [255, 0, 127],
    [255, 127, 0],
    [127, 255, 0],
    [0, 127, 255],
    [0, 255, 127],
]
hierarchy = hierarchy[0]
for i in range(len(contours)):
    area = cv2.contourArea(contours[i])
    if hierarchy[i][3] == 1:
        print (i, area)
        coln = (coln + 1) % len(colors)
        cv2.drawContours(orig, contours, i, colors[coln], -1)

cv2.imwrite("colored_map.png", orig)

Input image:

Output image:

Here I color only the direct descendants of the outmost contour (hierarchy[i][3] == 1). But you can change it to exclude the lakes.



来源:https://stackoverflow.com/questions/51183411/image-segmentation-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!