使用Python在OpenCV中存储
我想在图像中找到轮廓并进一步处理,例如在图像上绘制轮廓。 为此,我在不同的线程中运行了两个函数:使用Python在OpenCV中存储,python,opencv,Python,Opencv,我想在图像中找到轮廓并进一步处理,例如在图像上绘制轮廓。 为此,我在不同的线程中运行了两个函数: storage = cv.CreateMemStorage(0) contour = cv.FindContours(inData.content, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE) 及 每个函数在一个循环中运行,依次处理一个图像。 当一个函数完成时,它将图像放入一个缓冲区中,另一个函数可以从中获取图像。 这是可行的,
storage = cv.CreateMemStorage(0)
contour = cv.FindContours(inData.content, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE)
及
每个函数在一个循环中运行,依次处理一个图像。
当一个函数完成时,它将图像放入一个缓冲区中,另一个函数可以从中获取图像。
这是可行的,除了在结果中,轮廓在图像中绘制一个或两个图像,然后再绘制相应的图像
我认为这与OpenCV的存储有关,但我不明白为什么需要存储以及它的作用
编辑这里还有一些代码:我的程序是一个基于节点的图像分析软件。
以下是我当前代码的节点图:
|---------| |--------|
|-----| |-----|------>|Threshold|--->|Contours|--->|-------------| |------|
|Input|--->|Split| |---------| |--------| |Draw Contours|--->|Output|
|-----| |-----|----------------------------------->|-------------| |------|
这是从中派生所有节点的类:
from Buffer import Buffer
from threading import Thread
from Data import Data
class Node(Thread):
def __init__(self, inputbuffers, outputbuffers):
Thread.__init__(self)
self.inputbuffers = inputbuffers
self.outputbuffers = outputbuffers
def getInputBuffer(self, index):
return self.inputbuffers[index]
def getOutputBuffer(self, index):
return self.outputbuffers[index]
def _getContents(self, bufferArray):
out = []
for bufferToGet in bufferArray:
if bufferToGet and bufferToGet.data:
out.append(bufferToGet.data)
for bufferToGet in bufferArray:
bufferToGet.data = None
return out
def _allInputsPresent(self):
for bufferToChk in self.inputbuffers:
if not bufferToChk.data:
return False
return True
def _allOutputsEmpty(self):
for bufferToChk in self.outputbuffers:
if bufferToChk.data != None:
return False
return True
def _applyOutputs(self, output):
for i in range(len(output)):
if self.outputbuffers[i]:
self.outputbuffers[i].setData(output[i])
def run(self):
#Thread loop <------------------------------------
while True:
while not self._allInputsPresent(): pass
inputs = self._getContents(self.inputbuffers)
output = [None]*len(self.outputbuffers)
self.process(inputs, output)
while not self._allOutputsEmpty(): pass
self._applyOutputs(output)
def process(self, inputs, outputs):
'''
inputs: array of Data objects
outputs: array of Data objects
'''
pass
以下是节点:
from Node import Node
from Data import Data
import copy
import cv
class TemplateNode(Node):
def __init__(self, inputbuffers, outputbuffers):
super(type(self), self).__init__(inputbuffers, outputbuffers)
def process(self, inputs, outputs):
inData = inputs[0]
#Do something with the content e.g.
#cv.Smooth(inData.content, inData.content, cv.CV_GAUSSIAN, 11, 11)
outputs[0] = inData
class InputNode(Node):
def __init__(self, inputbuffers, outputbuffers):
super(InputNode, self).__init__(inputbuffers, outputbuffers)
self.capture = cv.CaptureFromFile("video.avi")
self.counter = 0
def process(self, inputs, outputs):
image = cv.QueryFrame(self.capture)
if image:
font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 3, 8)
x = 30
y = 50
cv.PutText(image, str(self.counter), (x,y), font, 255)
outputs[0] = Data(image,None,None,self.counter)
self.counter = self.counter+1
class OutputNode(Node):
def __init__(self, inputbuffers, outputbuffers, name):
super(type(self), self).__init__(inputbuffers, outputbuffers)
self.name = name
def process(self, inputs, outputs):
if type(inputs[0].content) == cv.iplimage:
cv.ShowImage(self.name, inputs[0].content)
cv.WaitKey()
class ThresholdNode(Node):
def __init__(self, inputbuffers, outputbuffers):
super(type(self), self).__init__(inputbuffers, outputbuffers)
def process(self, inputs, outputs):
inData = inputs[0]
inimg = cv.CreateImage(cv.GetSize(inData.content), cv.IPL_DEPTH_8U, 1);
cv.CvtColor(inData.content, inimg, cv.CV_BGR2GRAY)
outImg = cv.CreateImage(cv.GetSize(inimg), cv.IPL_DEPTH_8U, 1);
cv.Threshold(inimg, outImg, 70, 255, cv.CV_THRESH_BINARY_INV);
inData.content = outImg
outputs[0] = inData
class SplitNode(Node):
def __init__(self, inputbuffers, outputbuffers):
super(type(self), self).__init__(inputbuffers, outputbuffers)
def process(self, inputs, outputs):
inData = inputs[0]
if type(inData.content) == cv.iplimage:
imagecpy = cv.CloneImage(inData.content)
outputs[1] = Data(imagecpy, copy.copy(inData.time), copy.copy(inData.error), copy.copy(inData.number))
else:
outputs[1] = copy.deepcopy(inData)
print
class ContoursNode(Node):
def __init__(self, inputbuffers, outputbuffers):
super(type(self), self).__init__(inputbuffers, outputbuffers)
def process(self, inputs, outputs):
inData = inputs[0]
storage = cv.CreateMemStorage(0)
contours = cv.FindContours(inData.content, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE)
contoursArr = []
while contours:
points = []
for (x,y) in contours:
points.append((x,y))
contoursArr.append(points)
contours = contours.h_next()
outputs[0] = Data(contoursArr, inData.time, inData.error, inData.number)
pass
class DrawContoursNode(Node):
def __init__(self, inputbuffers, outputbuffers):
super(type(self), self).__init__(inputbuffers, outputbuffers)
def process(self, inputs, outputs):
inImg = inputs[0]
contours = inputs[1].content
print "Image start"
for cont in contours:
for (x,y) in cont:
cv.Circle(inImg.content, (x,y), 2, cv.CV_RGB(255, 0, 0))
print "Image end"
outputs[0] = inImg
这是主要功能。这里创建了所有节点和缓冲区
from NodeImpls import *
from Buffer import Buffer
buffer1 = Buffer()
buffer2 = Buffer()
buffer3 = Buffer()
buffer4 = Buffer()
buffer5 = Buffer()
buffer6 = Buffer()
innode = InputNode([], [buffer1])
split = SplitNode([buffer1], [buffer2, buffer3])
thresh = ThresholdNode([buffer3], [buffer4])
contours = ContoursNode([buffer4], [buffer5])
drawc = DrawContoursNode([buffer2, buffer5],[buffer6])
outnode = OutputNode([buffer6], [], "out1")
innode.start()
split.start()
thresh.start()
contours.start()
drawc.start()
outnode.start()
while True:
pass
缓冲区:
class Buffer(object):
def __init__(self):
self.data = None
def setData(self, data):
self.data = data
def getData(self):
return self.data
我认为这与OpenCV的存储有关,但我不明白为什么需要存储以及它的作用
存储只是一个保存结果的地方。OpenCV是一个C++库,依赖于手动内存分配,C++风格。Python绑定只是围绕它的一个薄薄的包装,并不是非常pythonic的。这就是为什么你必须手动分配存储,就像你在C或C++中那样做的。
我有两个函数在不同的线程中运行
...
这是可行的,除了在结果中,轮廓在图像中绘制一个或两个图像,然后再绘制相应的图像
我假设您的线程没有正确同步。这个问题可能与OpenCV无关,但与您拥有的函数、它们使用和传递的数据以及如何在它们之间共享数据有关
简而言之,请将您的代码张贴在创建线程和调用这些函数的地方,以及访问或修改
inImg
、inData
、contour
、contours
和storage
的地方。非常感谢您的帮助!我在问题中添加了我的代码。@AntonS在您的源代码中,我看到不同的线程(节点)共享相同的数据(缓冲区),而没有锁。最快的线程继续运行,并用新数据覆盖其输出缓冲区。为了同步每个生产者-消费者对,可以使用条件对象另一个链接:也可以考虑使用<代码> DeQue/代码>队列@安顿,事实上,我怀疑线程在这里有任何优势。数据流中没有并行性或并发性,通过适当的同步,所有线程都将等待最慢的线程(DrawContours?)。实际上,这意味着它们将像在正常的顺序代码中一样按顺序工作,但要组织正确的同步,需要付出更多的努力。像通常的函数一样实现节点,并在其中无限循环。同步问题解决后,您的代码更快(开销更少)且更易于维护。要点:我认为我的程序中存在并行性。没有平行分支是正确的,但例如,阈值节点可以处理图像10,而轮廓节点处理图像9。关于1。要点:我使用“队列”而不是缓冲区。但这没什么区别。我不明白为什么我必须同步线程:由于队列的原因,两个线程不应该尝试使用相同的映像。
from NodeImpls import *
from Buffer import Buffer
buffer1 = Buffer()
buffer2 = Buffer()
buffer3 = Buffer()
buffer4 = Buffer()
buffer5 = Buffer()
buffer6 = Buffer()
innode = InputNode([], [buffer1])
split = SplitNode([buffer1], [buffer2, buffer3])
thresh = ThresholdNode([buffer3], [buffer4])
contours = ContoursNode([buffer4], [buffer5])
drawc = DrawContoursNode([buffer2, buffer5],[buffer6])
outnode = OutputNode([buffer6], [], "out1")
innode.start()
split.start()
thresh.start()
contours.start()
drawc.start()
outnode.start()
while True:
pass
class Buffer(object):
def __init__(self):
self.data = None
def setData(self, data):
self.data = data
def getData(self):
return self.data