2011-02-27 1 views
2

J'essaie d'extraire les contours d'une image, de faire pivoter ces contours et de les insérer dans une nouvelle image. Le code est donné ci-dessous. Mon problème est dans la méthode de rotation des contours. Lorsque le code est exécuté, l'erreur suivante est vue "TypeError: l'objet 'cv.cvseq' ne prend pas en charge l'affectation d'élément".Changer les éléments d'un CvSeq en python

Une idée de la façon de résoudre ce problème? J'utilise des liaisons python pour Opencv 2.2.

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) 

Répondre

1

Il semble que vous ne pouvez pas modifier les éléments de l'objet cvseq en utilisant les liaisons Python (notez here que la liste des méthodes Python pour manipuler cvseq a des objets que des méthodes pour enlever les éléments de séquence et de modifier leur ordre.)

Les liaisons Python fournissent néanmoins les outils nécessaires pour atteindre votre objectif déclaré de faire pivoter les contours d'une image.

Puisque la méthode cv.DrawContours() nécessite une entrée cvseq, nous devons trouver une autre façon de dessiner les contours après les avoir stockés et manipulés en Python. Pour ce faire, utilisez les méthodes cv.FillPoly() ou cv.DrawPoly() (qui prennent en entrée une liste de listes de tuples) selon que le paramètre épaisseur qui aurait été transmis à cv.DrawContours() est -1 ou> 0 respectivement.

Ainsi, une façon de trouver les contours et d'en tirer leurs homologues mis en rotation, serait le suivant (où le centre de masse de chaque contour se trouve en redessinant sous forme remplie et en utilisant les fonctions de moment de 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) 
Questions connexes