2011-02-27 71 views
2

我试图从图像中提取轮廓,旋转这些轮廓并将它们插入到新图像中。代码如下。 我的问题是旋转轮廓方法。执行代码时会看到以下错误“TypeError:'cv.cvseq'对象不支持项目分配”。在python中更改CvSeq中的元素

如何解决这个问题的任何想法?我为Opencv 2.2使用python绑定。

import cv 

def rotateContour(contour, centerOfMass, angle): 
    for index in range(0, len(contour)): 
     contour[index] = rotatePoint(contour[index], centerOfMass, angle) 
    return contour 

def rotatePoint(point, centerOfMass, angle): 
    px, py = point 
    x, y = centerOfMass 
    temppoint = (px-x, py-y) 
    temppointx = temppoint[0]*math.cos(angle) + temppoint[1] * math.sin(angle) 
    temppointy = temppoint[1]*math.cos(angle) - temppoint[0] * math.sin(angle) 
    temppoint = (temppointx + x, temppointy + y) 

    return temppoint 

inputimage = cv.LoadImage('filename.png', cv.CV_LOAD_IMAGE_GRAYSCALE) 
outputimage = cv.CreateImage((10000, 300), 8, 1) 

storage = cv.CreateMemStorage (0) 
contours = cv.FindContours(inputimage, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE) 

for contour in contour_iterator(contours): 
    gray = cv.CV_RGB(200, 200, 200) 
    # Rotate contour somehow 
    contour = rotatecontour(contour) 
    cv.DrawContours(outputimage, contour, gray, gray, 0, -1, 8) 

cv.SaveImage("outputfile.png", outputimage) 

回答

1

看来你不能使用Python绑定改变cvseq对象的元素(注意here的Python方法操纵cvseq对象只有去除序列元素并改变它们的顺序中的方法列表。)

Python绑定仍然提供了工具来实现您在图像中旋转轮廓的既定目标。

由于cv.DrawContours()方法需要一个cvseq作为输入,我们必须找到一些其他的方式来绘制轮廓后,在Python中存储和操纵它们。一种方法是使用cv.FillPoly()cv.DrawPoly()方法(将元组列表作为输入),具体取决于将要传递给cv.DrawContours()的厚度参数是否分别为-1或> 0。

所以,一个办法的轮廓和借鉴他们的旋转同行,将是如下(其中每个轮廓的重心由填写的表格重绘和使用的OpenCV的时刻功能找到):

import cv 
import numpy as np 

# Draw contour from list of tuples. 
def draw_contour(im , contour , color , thickness = 1 , linetype = 8 , 
        shift = 0) : 
    if thickness == -1 : 
    cv.FillPoly(im , [contour] , color , linetype , shift) 
    else : 
    cv.PolyLine(im , [contour] , True , color , thickness , linetype , shift) 

# Rotate contour around centre point using numpy. 
def rotate_contour(contour , centre_point , theta) : 
    rotation = np.array([ [ np.cos(theta) , -np.sin(theta) ] , 
         [ np.sin(theta) , np.cos(theta) ] ]) 
    centre = np.vstack([ centre_point ] * len(contour)) 
    contour = np.vstack(contour) - centre 
    contour = np.dot(contour , rotation) + centre 
    return [ tuple (each_row) for each_row in contour ] 

# Find centre of mass by drawing contour in closed form and using moments. 
def find_centre_of_mass(contour) : 
    bottom_right = np.max(contour , axis = 0) 
    blank = cv.CreateImage(tuple (bottom_right) , 8 , 1) 
    cv.Set(blank , 0) 
    draw_contour(blank , contour , 1, -1) 
    moments = cv.Moments(blank , 1) 
    sM00 = float (cv.GetSpatialMoment(moments , 0 , 0)) 
    sM01 = float (cv.GetSpatialMoment(moments , 0 , 1)) 
    sM10 = float (cv.GetSpatialMoment(moments , 1 , 0)) 
    return (sM10/sM00 , sM01/sM00) 

THETA = np.pi/3.0 
COLOR = cv.CV_RGB(200 , 200 , 200) 
input_image = cv.LoadImage(‘filename.png’ , cv.CV_LOAD_IMAGE_GRAYSCALE) 
output_image = cv.CreateImage((input_image.width , input_image.height) , 
           input_image.depth , input_image.nChannels) 
cv.Set(output_image , 0) 

storage = cv.CreateMemStorage(0) 
contour_pointer = cv.FindContours(input_image , storage , 
            cv.CV_RETR_EXTERNAL , 
            cv.CV_CHAIN_APPROX_SIMPLE) 

while contour_pointer is not None : 
    contour = contour_pointer [ : ] 
    centre_of_mass = find_centre_of_mass(contour) 
    rotated_contour = rotate_contour(contour , centre_of_mass , THETA) 
    draw_contour(output_image , rotated_contour , COLOR , -1) 
    contour_pointer = contour_pointer.h_next() 

cv.SaveImage(‘outputfile.png’ , output_image)