Python 3.x 如何使用python3从图像中检测对象形状?

Python 3.x 如何使用python3从图像中检测对象形状?,python-3.x,image-processing,python-imaging-library,opencv3.0,Python 3.x,Image Processing,Python Imaging Library,Opencv3.0,我想用python3编写一个代码,从图像中检测对象和形状。 我想从给定图像中的一个对象中选择一个像素,然后找到相邻的像素。 如果它们具有相同的RGB值,则表示它们是对象的一部分。 当相邻像素改变RGB值,与原始像素的差值可调时,算法应停止搜索相邻像素。我认为这将工作,除非背景和对象有相同的颜色。 我已经找到了一种方法,将具有相同颜色的像素放在一个矩形中,但这对我没有帮助。我只想保存对象的形状,并将其放在不同的图像中。 比如说, 如果我想从对象的中间开始我的算法,让我们 假设一张黑表有白色

我想用python3编写一个代码,从图像中检测对象和形状。
我想从给定图像中的一个对象中选择一个像素,然后找到相邻的像素。
如果它们具有相同的RGB值,则表示它们是对象的一部分。

当相邻像素改变RGB值,与原始像素的差值可调时,算法应停止搜索相邻像素。我认为这将工作,除非背景和对象有相同的颜色。

我已经找到了一种方法,将具有相同颜色的像素放在一个矩形中,但这对我没有帮助。我只想保存对象的形状,并将其放在不同的图像中。

比如说,

如果我想从对象的中间开始我的算法,让我们 假设一张黑表有白色背景,算法会发现 在任何方向上具有相同颜色的像素

当相邻像素 RGB值将在一个方向上改变超过30个单位 算法将停止朝那个方向前进,并开始朝那个方向前进 另一个方向,直到我有了桌子的形状



我在另一篇文章中发现了一个代码,它可以帮助我使用PIL确定具有共享值的像素区域


谢谢

从集合导入defaultdict
从PIL导入图像,ImageDraw
def连接的_部件(边缘):
"""
给定由边(即节点对)表示的图,生成其
作为节点集连接的组件。
时间复杂度与边数成线性关系。
"""
邻居=默认DICT(设置)
对于边中的a、b:
邻居[a]。添加(b)
邻居[b]。添加(a)
seen=set()
def组件(节点,邻居=邻居,看见=看见,看见=看见。添加):
不可见=设置([节点])
next_unseen=unseen.pop
虽然看不见:
node=next_unseen()
请参阅(节点)
看不见|=邻居[节点]-看到
屈服点
返回(为邻居中的节点设置(组件(节点)),如果节点不在视图中)
def匹配_像素(图像,测试):
"""
生成像素满足测试要求的所有像素坐标。
"""
宽度,高度=image.size
像素=image.load()
对于x范围内的x(宽度):
对于X范围内的y(高度):
如果测试(像素[x,y]):
产量x,y
def make_边(坐标):
"""
生成所有相邻像素坐标对。
"""
坐标=设置(坐标)
对于坐标中的x,y:
如果(x-1,y-1)在坐标中:
收益率(x,y),(x-1,y-1)
如果(x,y-1)在坐标系中:
收益率(x,y),(x,y-1)
如果(x+1,y-1)在坐标中:
收益率(x,y),(x+1,y-1)
如果(x-1,y)在坐标中:
收益率(x,y),(x-1,y)
收益率(x,y),(x,y)
def边界框(坐标):
"""
返回所有坐标的边界框。
"""
xs,ys=zip(*坐标)
返回最小值(xs)、最小值(ys)、最大值(xs)、最大值(ys)
def不相交区域(图像,测试):
"""
返回所有非连续区域的边界框
谁在测试。
"""
对于每个in-connected_组件(生成_边(匹配_像素(图像,测试)):
屈服边界框(每个)
def是否足够黑(像素):
r、 g,b=像素
返回r<10,g<10,b<10
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
image=image.open('some_image.jpg'))
draw=ImageDraw.draw(图像)
对于不相交区域中的rect(图像,黑色是否足够):
矩形(矩形,轮廓=(255,0,0))
image.show()

尝试将opencv与Python结合使用。 使用opencv,您可以进行高级图像分析,并且有许多教程可以使用它。

from collections import defaultdict
from PIL import Image, ImageDraw


def connected_components(edges):
"""
Given a graph represented by edges (i.e. pairs of nodes), generate its
connected components as sets of nodes.

Time complexity is linear with respect to the number of edges.
"""
neighbors = defaultdict(set)
for a, b in edges:
    neighbors[a].add(b)
    neighbors[b].add(a)
seen = set()
def component(node, neighbors=neighbors, seen=seen, see=seen.add):
    unseen = set([node])
    next_unseen = unseen.pop
    while unseen:
        node = next_unseen()
        see(node)
        unseen |= neighbors[node] - seen
        yield node
return (set(component(node)) for node in neighbors if node not in seen)


def matching_pixels(image, test):
"""
Generate all pixel coordinates where pixel satisfies test.
"""
  width, height = image.size
  pixels = image.load()
  for x in xrange(width):
    for y in xrange(height):
        if test(pixels[x, y]):
            yield x, y


def make_edges(coordinates):
"""
Generate all pairs of neighboring pixel coordinates.
"""
  coordinates = set(coordinates)
  for x, y in coordinates:
      if (x - 1, y - 1) in coordinates:
          yield (x, y), (x - 1, y - 1)
      if (x, y - 1) in coordinates:
          yield (x, y), (x, y - 1)
      if (x + 1, y - 1) in coordinates:
        yield (x, y), (x + 1, y - 1)
      if (x - 1, y) in coordinates:
        yield (x, y), (x - 1, y)
      yield (x, y), (x, y)


def boundingbox(coordinates):
"""
Return the bounding box of all coordinates.
"""
  xs, ys = zip(*coordinates)
  return min(xs), min(ys), max(xs), max(ys)


def disjoint_areas(image, test):
"""
Return the bounding boxes of all non-consecutive areas
who's pixels satisfy test.
"""
  for each in connected_components(make_edges(matching_pixels(image, test))):
    yield boundingbox(each)


def is_black_enough(pixel):
  r, g, b = pixel
  return r < 10 and g < 10 and b < 10


if __name__ == '__main__':

  image = Image.open('some_image.jpg')
  draw = ImageDraw.Draw(image)
  for rect in disjoint_areas(image, is_black_enough):
      draw.rectangle(rect, outline=(255, 0, 0))
  image.show()