static void find_three_point_rectangle_triangle (Rectangle *r, Point points[4], gint p) { Point a = points[p % 4]; /* 0 1 2 3 */ Point b = points[(p + 1) % 4]; /* 1 2 3 0 */ Point c = points[(p + 2) % 4]; /* 2 3 0 1 */ Point d = points[(p + 3) % 4]; /* 3 0 1 2 */ Point i1; /* intersection point */ Point i2; /* intersection point */ Point mid; mid.x = (a.x + b.x) / 2.0; mid.y = (a.y + b.y) / 2.0; if (intersect_x (b, c, mid, &i1) && intersect_y (a, d, mid, &i2)) add_rectangle (points, r, mid, mid, i1, i2); if (intersect_y (b, c, mid, &i1) && intersect_x (a, d, mid, &i2)) add_rectangle (points, r, mid, mid, i1, i2); if (intersect_x (a, d, mid, &i1) && intersect_y (b, c, mid, &i2)) add_rectangle (points, r, mid, mid, i1, i2); if (intersect_y (a, d, mid, &i1) && intersect_x (b, c, mid, &i2)) add_rectangle (points, r, mid, mid, i1, i2); }
static void add_rectangle (cairo_t *cr, double size) { double x, y; if (size < 1) return; cairo_get_current_point (cr, &x, &y); cairo_rel_move_to (cr, -size/2., -size/2.); cairo_rel_line_to (cr, size, 0); cairo_rel_line_to (cr, 0, size); cairo_rel_line_to (cr, -size, 0); cairo_close_path (cr); cairo_save (cr); cairo_translate (cr, -size/2., size); cairo_move_to (cr, x, y); cairo_rotate (cr, M_PI/4); add_rectangle (cr, size / M_SQRT2); cairo_restore (cr); cairo_save (cr); cairo_translate (cr, size/2., size); cairo_move_to (cr, x, y); cairo_rotate (cr, -M_PI/4); add_rectangle (cr, size / M_SQRT2); cairo_restore (cr); }
static void find_two_point_rectangle (Rectangle *r, Point points[4], gint p) { Point a = points[ p % 4]; /* 0 1 2 3 */ Point b = points[(p + 1) % 4]; /* 1 2 3 0 */ Point c = points[(p + 2) % 4]; /* 2 3 0 1 */ Point d = points[(p + 3) % 4]; /* 3 0 1 2 */ Point i1; /* intersection point */ Point i2; /* intersection point */ Point mid; /* Mid point */ add_rectangle (points, r, a, a, c, c); add_rectangle (points, r, b, b, d, d); if (intersect_x (c, b, a, &i1) && intersect_y (c, b, a, &i2)) { mid.x = ( i1.x + i2.x ) / 2.0; mid.y = ( i1.y + i2.y ) / 2.0; add_rectangle (points, r, a, a, mid, mid); } }
static void find_three_point_rectangle_corner (Rectangle *r, Point points[4], gint p) { Point a = points[p % 4]; /* 0 1 2 3 */ Point b = points[(p + 1) % 4]; /* 1 2 3 0 */ Point c = points[(p + 2) % 4]; /* 2 3 0 2 */ Point d = points[(p + 3) % 4]; /* 3 0 2 1 */ Point i1; /* intersection point */ Point i2; /* intersection point */ if (intersect_x (b, c, a , &i1) && intersect_y (c, d, i1, &i2)) add_rectangle (points, r, a, a, i1, i2); if (intersect_y (b, c, a , &i1) && intersect_x (c, d, i1, &i2)) add_rectangle (points, r, a, a, i1, i2); if (intersect_x (c, d, a , &i1) && intersect_y (b, c, i1, &i2)) add_rectangle (points, r, a, a, i1, i2); if (intersect_y (c, d, a , &i1) && intersect_x (b, c, i1, &i2)) add_rectangle (points, r, a, a, i1, i2); }
static void modify_placement (SWFMovie movie, guint mod) { SWFDisplayItem item; SWFBlock clip, clip2; clip = (SWFBlock) newSWFMovieClip (); add_rectangle ((SWFMovieClip) clip, 255, 0, 0); SWFMovieClip_nextFrame ((SWFMovieClip) clip); clip2 = (SWFBlock) newSWFMovieClip (); add_rectangle ((SWFMovieClip) clip2, 0, 0, 255); SWFMovieClip_nextFrame ((SWFMovieClip) clip2); item = SWFMovie_add (movie, clip); SWFDisplayItem_setDepth (item, 1); SWFDisplayItem_setName (item, "a"); SWFMovie_nextFrame (movie); item = SWFMovie_add (movie, clip2); SWFDisplayItem_setDepth (item, 1); SWFDisplayItem_moveTo (item, 20, 20); SWFDisplayItem_setName (item, "b"); }
static cairo_perf_ticks_t do_pythagoras_tree (cairo_t *cr, int width, int height) { double size = 128; cairo_perf_timer_start (); cairo_save (cr); cairo_translate (cr, 0, height); cairo_scale (cr, 1, -1); cairo_move_to (cr, width/2, size/2); add_rectangle (cr, size); cairo_set_source_rgb (cr, 0., 0., 0.); cairo_fill (cr); cairo_restore (cr); cairo_perf_timer_stop (); return cairo_perf_timer_elapsed (); }
static void find_maximum_aspect_rectangle (Rectangle *r, Point points[4], gint p) { Point a = points[ p % 4]; /* 0 1 2 3 */ Point b = points[(p + 1) % 4]; /* 1 2 3 0 */ Point c = points[(p + 2) % 4]; /* 2 3 0 1 */ Point d = points[(p + 3) % 4]; /* 3 0 1 2 */ Point i1; /* intersection point */ Point i2; /* intersection point */ Point i3; /* intersection point */ if (intersect_x (b, c, a, &i1)) { i2.x = i1.x + 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (c, d, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); i2.x = i1.x - 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (c, d, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); } if (intersect_y (b, c, a, &i1)) { i2.x = i1.x + 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (c, d, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); i2.x = i1.x - 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (c, d, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); } if (intersect_x (c, d, a, &i1)) { i2.x = i1.x + 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (b, c, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); i2.x = i1.x - 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (b, c, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); } if (intersect_y (c, d, a, &i1)) { i2.x = i1.x + 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (b, c, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); i2.x = i1.x - 1.0 * r->aspect; i2.y = i1.y + 1.0; if (intersect (d, a, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (a, b, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); if (intersect (b, c, i1, i2, &i3)) add_rectangle (points, r, i1, i3, i1, i3); } }
std::vector<rectangle_t> detect_rectangles(image_t& img,filter_func_t fn,size_t tolerance) { h_decomp_t hd; std::vector<rectangle_t> rects; rgb_color_t col(255,0,0); if(!process_image(img,fn,col)) return rects; if(!do_h_decomposition(img,hd,col)) return rects; std::vector<edge_detection_t> edges; printf("[processing] apply approximate H/V edge detection with tolerance %u\n",tolerance); for(size_t i=0;i<hd.blocks.size();i++) { const size_t edge_detection_min_w=50; const v_block_decomp_t& b=hd.blocks[i]; edge_detection_t ed=do_approx_edge_detection(b,tolerance,edge_detection_min_w); printf("[processing] block %u: filtering artecfacts...",i); filter_edge_detection(ed.left); filter_edge_detection(ed.right); printf("[processing] %u segment left/%u segment right\n",ed.left.size(),ed.right.size()); if(ed.left.size()==1 && ed.right.size()==1) { edges.push_back(ed); continue; } printf("[processing block %u: complex decomposition: splitting...",i); size_t left=0,right=0; size_t nb_pieces=0; while(left!=ed.left.size() && right!=ed.right.size()) { // update left if necessary while(left<ed.left.size() && ed.left[left].end.y<=ed.right[right].orig.y) left++; if(left==ed.left.size()) break; // update right while(right<ed.right.size() && ed.right[right].end.y<=ed.left[left].orig.y) right++; if(right==ed.right.size()) break; // add to list edge_detection_t new_ed; new_ed.left.push_back(ed.left[left]); new_ed.right.push_back(ed.right[right]); // normalize size_t uy=std::max(new_ed.left[0].orig.y,new_ed.right[0].orig.y); size_t dy=std::min(new_ed.left[0].end.y,new_ed.right[0].end.y); new_ed.left[0].orig.y=new_ed.right[0].orig.y=uy; new_ed.left[0].end.y=new_ed.right[0].end.y=dy; new_ed.left[0].len=new_ed.right[0].len=dy-uy+1; edges.push_back(new_ed); nb_pieces++; // find first end if(ed.left[left].end.y<ed.right[right].end.y) left++; else right++; } printf("[processing] got %u pieces\n",nb_pieces); } for(size_t i=0;i<edges.size();i++) { const edge_detection_t ed=edges[i]; if(ed.left.size()==1 && ed.right.size()==1) { size_t up_y=std::max(ed.left[0].orig.y,ed.right[0].orig.y); size_t down_y=std::min(ed.left[0].end.y,ed.right[0].end.y); rectangle_t r; r.x=ed.left[0].orig.x; r.y=up_y; r.h=down_y-up_y+1; r.w=ed.right[0].orig.x-ed.left[0].orig.x+1; // doing an approximation: the really diameter is not the visible diameter const size_t min_w=30; if(r.w<=min_w) continue; // doing an approximation: the really diameter is not the visible diameter float ratio=float(r.w)/float(r.h); const float expected_ratio=2.3; const float max_ratio_delta=0.7; float perfect_division=expected_ratio/ratio; long nearest=lround(perfect_division); float delta=fabs(perfect_division-nearest); printf("[processing] perfect_div=%f delta=%f\n",perfect_division,delta); // doing some calculus gives us the following formula: // for each rectangle to be within range, one must have: // delta<H/W*max_ratio_delta if(delta<(r.h*max_ratio_delta/r.w)) { r.h/=nearest; //printf("[main] ratio=%f\n",float(r.w)/r.h); for(long j=0;j<nearest;j++) { r.y=up_y+j*r.h; add_rectangle(rects,r); } } else { long H=r.h; long Y=r.y; r.h=r.w/expected_ratio; nearest=floor(H/r.h); for(long i=0;i<nearest;i++) { r.y=Y+H-i*r.h; add_rectangle(rects,r); } } } else { printf("[processing] got non-standard edge decomposition: %u left, %u right. Give up...\n",ed.left.size(),ed.right.size()); } } return rects; }