/* 寻找能合并成长线段的线段集合 * lineSegments 所有线段的数组 * lineSetArray lineSegments数组 * <return>线段集合构成的数组</return> */ LineSetArray* groupLineSegments(SegmentsArray* lineSegments, LineSetArray* lineSetArray) { /*****寻找能合并成长线段的线段集合*****/ for(int i=0; i<lineSegments->count; i++) { if(lineSegments->flag[i] == 0) { int k=0; //k为当前正在处理的tempLineSet中线段的索引 SegmentsArray tempLineSet = {5, 0, (CvPoint2D32f(*)[2])malloc(5*sizeof(CvPoint2D32f[2])), (char*)malloc(5*sizeof(char))}; tempLineSet.pointArray[tempLineSet.count][0] = lineSegments->pointArray[i][0]; tempLineSet.pointArray[tempLineSet.count][1] = lineSegments->pointArray[i][1]; (tempLineSet.count)++; lineSegments->flag[i] = 1; while(k<tempLineSet.count) //如果tempLineSet中还有未处理的线段 { for(int j=i+1; j<lineSegments->count; j++) { if(lineSegments->flag[j] == 0) { if(mergeLineJudge(&(tempLineSet.pointArray[k][0]), &(tempLineSet.pointArray[k][1]), &(lineSegments->pointArray[j][0]), &(lineSegments->pointArray[j][1]), (float)(M_PI/ANGLE_THRESHOLD), (float)DISTANCE_THRESHOLD)) { /*****如果tempLineSet内存不够,则将数组长度+5*****/ if(tempLineSet.count >= tempLineSet.length) { tempLineSet.length += 5; CvPoint2D32f (*tempPointArray)[2]; char* tempFlag; tempPointArray = (CvPoint2D32f(*)[2])malloc(sizeof(CvPoint2D32f[2]) * tempLineSet.length); tempFlag = (char*)malloc(sizeof(char) * tempLineSet.length); for(int m=0; m<tempLineSet.count; m++) { tempPointArray[m][0] = tempLineSet.pointArray[m][0]; tempPointArray[m][1] = tempLineSet.pointArray[m][1]; tempFlag[m] = tempLineSet.flag[m]; } free(tempLineSet.pointArray); free(tempLineSet.flag); tempLineSet.pointArray = tempPointArray; tempLineSet.flag = tempFlag; } tempLineSet.pointArray[tempLineSet.count][0] = lineSegments->pointArray[j][0]; tempLineSet.pointArray[tempLineSet.count][1] = lineSegments->pointArray[j][1]; (tempLineSet.count)++; lineSegments->flag[j] = 1; } } } k++; } lineSetArray->lineSet[lineSetArray->count] = tempLineSet; (lineSetArray->count)++; /*****如果lineSetArray内存不够,则将数组长度+10*****/ if(lineSetArray->count >= lineSetArray->length) { lineSetArray->length += 10; SegmentsArray* tempSegmentsArray = (SegmentsArray*)malloc(lineSetArray->length * sizeof(SegmentsArray)); for(int m=0; m<lineSetArray->count; m++) { tempSegmentsArray[m] = lineSetArray->lineSet[m]; } free(lineSetArray->lineSet); lineSetArray->lineSet = tempSegmentsArray; } } } return lineSetArray; }
void draw() { double scale = this->scale == 0? 1.0 : this->scale; CvScalar colors[5] = { #if !defined CV_VERSION_EPOCH && (CV_VERSION_MAJOR >= 3) CvScalar(cvRound(color[0].r * 255), cvRound(color[0].g * 255), cvRound(color[0].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[1].r * 255), cvRound(color[1].g * 255), cvRound(color[1].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[2].r * 255), cvRound(color[2].g * 255), cvRound(color[2].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[3].r * 255), cvRound(color[3].g * 255), cvRound(color[3].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[4].r * 255), cvRound(color[4].g * 255), cvRound(color[4].b * 255), cvRound(alpha * 255)), #else {{cvRound(color[0].r * 255), cvRound(color[0].g * 255), cvRound(color[0].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[1].r * 255), cvRound(color[1].g * 255), cvRound(color[1].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[2].r * 255), cvRound(color[2].g * 255), cvRound(color[2].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[3].r * 255), cvRound(color[3].g * 255), cvRound(color[3].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[4].r * 255), cvRound(color[4].g * 255), cvRound(color[4].b * 255), cvRound(alpha * 255)}}, #endif }; for (int i = 0; i < (objects ? objects->total : 0); i++) { CvRect* r = (CvRect*) cvGetSeqElem(objects, i); CvPoint center; int thickness = stroke <= 0? CV_FILLED : cvRound(stroke * 100); int linetype = antialias? CV_AA : 8; center.x = cvRound((r->x + r->width * 0.5) / scale); center.y = cvRound((r->y + r->height * 0.5) / scale); switch (shape == 1.0? (rand() % 3) : cvRound(shape * 10)) { default: case 0: { int radius = cvRound((r->width + r->height) * 0.25 / scale); cvCircle(image, center, radius, colors[i % 5], thickness, linetype); break; } case 1: { #if !defined CV_VERSION_EPOCH && (CV_VERSION_MAJOR >= 3) CvBox2D box = CvBox2D(CvPoint2D32f(center.x, center.y), CvSize2D32f(r->width / scale, (r->height / scale) * 1.2), 90); #else CvBox2D box = {{center.x, center.y}, {r->width / scale, (r->height / scale) * 1.2}, 90}; #endif cvEllipseBox(image, box, colors[i % 5], thickness, linetype); break; } case 2: { #if !defined CV_VERSION_EPOCH && (CV_VERSION_MAJOR >= 3) CvPoint pt1 = CvPoint(r->x / scale, r->y / scale); CvPoint pt2 = CvPoint((r->x + r->width) / scale, (r->y + r->height) / scale); #else CvPoint pt1 = {r->x / scale, r->y / scale}; CvPoint pt2 = {(r->x + r->width) / scale, (r->y + r->height) / scale}; #endif cvRectangle(image, pt1, pt2, colors[i % 5], thickness, linetype); break; } } } }
/* 将矢量化结果中的拐角线从拐点处断开,并先合并平行相连的线段 * potrace_state 矢量化输出结果 * lineSegments 拐角点断开并合并后的线段数组 */ void breakCornerAndRecombine(potrace_state_t* potrace_state, SegmentsArray* lineSegments) { int i; potrace_path_t* pNext = potrace_state->plist; while(pNext != NULL) { potrace_curve_t* curve = &(pNext->curve); /*****为lineSegments增加curve->n的数组长度*****/ lineSegments->length = lineSegments->count+2*curve->n; CvPoint2D32f (*tempPointArray)[2]; char* tempFlag; tempPointArray = (CvPoint2D32f(*)[2])malloc(sizeof(CvPoint2D32f[2]) * lineSegments->length); tempFlag = (char*)malloc(sizeof(char) * lineSegments->length); for(int m=0; m<lineSegments->count; m++) { tempPointArray[m][0] = lineSegments->pointArray[m][0]; tempPointArray[m][1] = lineSegments->pointArray[m][1]; tempFlag[m] = lineSegments->flag[m]; } free(lineSegments->pointArray); free(lineSegments->flag); lineSegments->pointArray = tempPointArray; lineSegments->flag = tempFlag; for(i=0; i<curve->n; i++) //遍历闭合曲线中的每个片段 { if(curve->tag[i] == POTRACE_CORNER) //如果是拐角线片段 { lineSegments->flag[lineSegments->count] = 0; //每次循环存储的是当前拐角线的第二个直线片段和下一个拐角线的第一个直线片段 lineSegments->pointArray[lineSegments->count][0].x = (float)curve->c[i][1].x; lineSegments->pointArray[lineSegments->count][0].y = (float)curve->c[i][1].y; lineSegments->pointArray[lineSegments->count][1].x = (float)curve->c[i][2].x; lineSegments->pointArray[lineSegments->count][1].y = (float)curve->c[i][2].y; (lineSegments->count)++; lineSegments->flag[lineSegments->count] = 0; lineSegments->pointArray[lineSegments->count][0].x = (float)curve->c[i][2].x; lineSegments->pointArray[lineSegments->count][0].y = (float)curve->c[i][2].y; if(i == curve->n-1) //最后一个曲线片段的下一个拐角线是第一个拐角线 { lineSegments->pointArray[lineSegments->count][1].x = (float)curve->c[0][1].x; lineSegments->pointArray[lineSegments->count][1].y = (float)curve->c[0][1].y; } else { lineSegments->pointArray[lineSegments->count][1].x = (float)curve->c[i+1][1].x; lineSegments->pointArray[lineSegments->count][1].y = (float)curve->c[i+1][1].y; } (lineSegments->count)++; //判断该次循环存储的两个直线片段是否能构成一条长直线 if(mergeLineJudge(&(lineSegments->pointArray[lineSegments->count-2][0]), &(lineSegments->pointArray[lineSegments->count-2][1]), &(lineSegments->pointArray[lineSegments->count-1][0]), &(lineSegments->pointArray[lineSegments->count-1][1]), (float)(M_PI/ANGLE_THRESHOLD), (float)DISTANCE_THRESHOLD)) { CvPoint2D32f* temp = mergeLine(&(lineSegments->pointArray[lineSegments->count-2][0]), &(lineSegments->pointArray[lineSegments->count-2][1]), &(lineSegments->pointArray[lineSegments->count-1][0]), &(lineSegments->pointArray[lineSegments->count-1][1])); lineSegments->pointArray[lineSegments->count-2][0] = temp[0]; lineSegments->pointArray[lineSegments->count-2][1] = temp[1]; lineSegments->flag[lineSegments->count-1] = 1; } } } pNext = pNext->next; } }