2010-09-24 8 views
1

J'ai un problème avec le rognage de l'image en utilisant la bibliothèque OpenCV sur iPhone. J'ai une image avec la zone sélectionnée et je voudrais recadrer l'image avec cette zone. Mais la nouvelle image n'est pas carte au rectangle et la nouvelle image a aussi la couleur bleue du texte.Recadrer l'image avec OpenCV

J'utiliser ce code à l'image des cultures:

IplImage *src = [OpenCV CreateIplImageFromUIImage:image]; 


NSValue *val = [corners objectAtIndex:0]; 
CGPoint p1 = [val CGPointValue]; 
val = [corners objectAtIndex:1]; 
CGPoint p2 = [val CGPointValue]; 
val = [corners objectAtIndex:2]; 
CGPoint p3 = [val CGPointValue]; 
val = [corners objectAtIndex:3]; 
CGPoint p4 = [val CGPointValue]; 

float minX = fmin(fmin(p1.x, p2.x), fmin(p3.x, p4.x)); 
float minY = fmin(fmin(p1.y, p2.y), fmin(p3.y, p4.y)); 
float maxX = fmax(fmax(p1.x, p2.x), fmax(p3.x, p4.x)); 
float maxY = fmax(fmax(p1.y, p2.y), fmax(p3.y, p4.y)); 

CGFloat width = maxX - minX; 
CGFloat height = maxY - minY; 

IplImage *dst = cvCreateImage(cvSize(width, height), 8, 3); 

p1 = CGPointMake(p1.x - minX, p1.y - minY); 
p2 = CGPointMake(p2.x - minX, p2.y - minY); 
p3 = CGPointMake(p3.x - minX, p3.y - minY); 
p4 = CGPointMake(p4.x - minX, p4.y - minY); 

IplImage* cropped = cvCreateImage(cvSize(width, height), src->depth, src->nChannels); 

cvSetImageROI(src, cvRect(minX, minY, width, height)); 

cvCopy(src, cropped, NULL); 
cvResetImageROI(src); 
cvReleaseImage(&src); 

CvMat* mmat = cvCreateMat(3, 3, CV_32FC1); 

CvPoint2D32f *c1 = (CvPoint2D32f *)malloc(4 * sizeof(CvPoint2D32f)); 
CvPoint2D32f *c2 = (CvPoint2D32f *)malloc(4 * sizeof(CvPoint2D32f)); 

c1[0].x = p1.x; c1[0].y = p1.y; 
c1[1].x = p4.x; c1[1].y = p4.y; 
c1[2].x = p2.x; c1[2].y = p2.y; 
c1[3].x = p3.y; c1[3].y = p3.y; 

c2[0].x = 0; c2[0].y = 0; 
c2[1].x = width; c2[1].y = 0; 
c2[2].x = 0; c2[2].y = height; 
c2[3].x = width; c2[3].y = height; 

    mmat = cvGetPerspectiveTransform(c1, c2, mmat); 
cvWarpPerspective(cropped, dst, mmat, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); 

Je serai reconnaissant pour toute aide.

+0

Pourquoi n'essayez-vous pas de voir l'image recadrée sans utiliser la chaîne? – rics

+0

Les sélectionnés ne peuvent pas être un rectangle. Il peut s'agir de n'importe quel quadrilatère et j'aimerais d'abord recadrer l'image sur ce quadrilatère, puis mapper ce quadrilatère au rectangle. Mais avec la fonction ci-dessus, je peux seulement recadrer l'image à la zone rectangle et le gauchissement ne fonctionne pas bien. –

+0

comment nous détectons les coins? Pouvez-vous me fournir des lignes directrices ou un code peu? – QueueOverFlow

Répondre

2

J'ai eu une erreur dans mon code. Si quelqu'un est intéressé, voici le code de travail:

IplImage *src = [OpenCV CreateIplImageFromUIImage:image]; 

IplImage *dst = cvCloneImage(src); 
dst->origin = src->origin; 
dst->nChannels = src->nChannels; 
dst->depth = src->depth; 

cvZero(dst); 

NSValue *val = [corners objectAtIndex:0]; 
CGPoint p1 = [val CGPointValue]; 
val = [corners objectAtIndex:1]; 
CGPoint p2 = [val CGPointValue]; 
val = [corners objectAtIndex:2]; 
CGPoint p3 = [val CGPointValue]; 
val = [corners objectAtIndex:3]; 
CGPoint p4 = [val CGPointValue]; 

CGFloat width = src->width; 
CGFloat height = src->height; 

CvMat* mmat = cvCreateMat(3, 3, CV_32FC1); 

CvPoint2D32f *c1 = (CvPoint2D32f *)malloc(4 * sizeof(CvPoint2D32f)); 
CvPoint2D32f *c2 = (CvPoint2D32f *)malloc(4 * sizeof(CvPoint2D32f)); 

c1[0].x = round(p1.x); c1[0].y = round(p1.y); 
c1[1].x = round(p4.x); c1[1].y = round(p4.y); 
c1[2].x = round(p2.x); c1[2].y = round(p2.y); 
c1[3].x = round(p3.x); c1[3].y = round(p3.y); 

c2[0].x = 0;   c2[0].y = 0; 
c2[1].x = width -1;  c2[1].y = 0; 
c2[2].x = 0;   c2[2].y = height - 1; 
c2[3].x = width - 1; c2[3].y = height - 1; 

mmat = cvGetPerspectiveTransform(c1, c2, mmat); 
free(c1); 
free(c2); 

cvWarpPerspective(src, dst, mmat, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); 

cvReleaseImage(&src); 
cvReleaseMat(&mmat); 

UIImage *newImage = [OpenCV UIImageFromIplImage:dst]; 
cvReleaseImage(&dst);