int CharacterCut::loadImage(String imagePath){

		Mat image = imread(imagePath,0);  
		if(!image.data)  
		{  
			cout << "Fail to load image" << endl;  
			return 0;  
		}  
		//局部自适应二值化
		Mat imageShold;  
		int blockSize = 25;
		int constValue = 10;
		adaptiveThreshold(image, imageShold, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, blockSize, constValue);
		//腐蚀
		Mat img_erode;
		erode(imageShold,img_erode,Mat()); 
		//查找连通域
		vector<vector<Point>> contours;  
		findContours(img_erode, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0));  
		//筛选连通域大小
		getSizeContours(contours); 
		//初次分割 基于连通域
		vector<Rect> firstCut;
		//利用连通域矩形 提取单字
		for(int i=0;i<contours.size();i++){
			Rect r=boundingRect(Mat(contours[i]));
			rectangle(image,r,Scalar(0),1);
			Rect rect(r.x,r.y,r.width,r.height);

			firstCut.push_back(rect);
		}

		//连通域排序
		sortContours(firstCut); 
		//求平均宽度
		int m=findEvenwidth(firstCut,imageShold);
		//连通域合并
		mergeContours(firstCut,m);	
		//cout<<"EvenWidth: "<<m<<endl;
		vector<Rect>::reverse_iterator it;
		//投影分割
		for(it=firstCut.rbegin();it!=firstCut.rend();it++){
			secondCut(imageShold((*it)),m);
		} 
		return 1;  
	}
Пример #2
0
static void mergeRegionHoles(rcContext* ctx, rcContourRegion& region)
{
	// Sort holes from left to right.
	for (int i = 0; i < region.nholes; i++)
		findLeftMostVertex(region.holes[i].contour, &region.holes[i].minx, &region.holes[i].minz, &region.holes[i].leftmost);
	
	qsort(region.holes, region.nholes, sizeof(rcContourHole), compareHoles);
	
	int maxVerts = region.outline->nverts;
	for (int i = 0; i < region.nholes; i++)
		maxVerts += region.holes[i].contour->nverts;
	
	rcScopedDelete<rcPotentialDiagonal> diags = (rcPotentialDiagonal*)rcAlloc(sizeof(rcPotentialDiagonal)*maxVerts, RC_ALLOC_TEMP);
	if (!diags)
	{
		ctx->log(RC_LOG_WARNING, "mergeRegionHoles: Failed to allocated diags %d.", maxVerts);
		return;
	}
	
	rcContour* outline = region.outline;
	
	// Merge holes into the outline one by one.
	for (int i = 0; i < region.nholes; i++)
	{
		rcContour* hole = region.holes[i].contour;
		
		int index = -1;
		int bestVertex = region.holes[i].leftmost;
		for (int iter = 0; iter < hole->nverts; iter++)
		{
			// Find potential diagonals.
			// The 'best' vertex must be in the cone described by 3 cosequtive vertices of the outline.
			// ..o j-1
			//   |
			//   |   * best
			//   |
			// j o-----o j+1
			//         :
			int ndiags = 0;
			const int* corner = &hole->verts[bestVertex*4];
			for (int j = 0; j < outline->nverts; j++)
			{
				if (inCone(j, outline->nverts, outline->verts, corner))
				{
					int dx = outline->verts[j*4+0] - corner[0];
					int dz = outline->verts[j*4+2] - corner[2];
					diags[ndiags].vert = j;
					diags[ndiags].dist = dx*dx + dz*dz;
					ndiags++;
				}
			}
			// Sort potential diagonals by distance, we want to make the connection as short as possible.
			qsort(diags, ndiags, sizeof(rcPotentialDiagonal), compareDiagDist);
			
			// Find a diagonal that is not intersecting the outline not the remaining holes.
			index = -1;
			for (int j = 0; j < ndiags; j++)
			{
				const int* pt = &outline->verts[diags[j].vert*4];
				bool intersect = intersectSegCountour(pt, corner, diags[i].vert, outline->nverts, outline->verts);
				for (int k = i; k < region.nholes && !intersect; k++)
					intersect |= intersectSegCountour(pt, corner, -1, region.holes[k].contour->nverts, region.holes[k].contour->verts);
				if (!intersect)
				{
					index = diags[j].vert;
					break;
				}
			}
			// If found non-intersecting diagonal, stop looking.
			if (index != -1)
				break;
			// All the potential diagonals for the current vertex were intersecting, try next vertex.
			bestVertex = (bestVertex + 1) % hole->nverts;
		}
		
		if (index == -1)
		{
			ctx->log(RC_LOG_WARNING, "mergeHoles: Failed to find merge points for %p and %p.", region.outline, hole);
			continue;
		}
		if (!mergeContours(*region.outline, *hole, index, bestVertex))
		{
			ctx->log(RC_LOG_WARNING, "mergeHoles: Failed to merge contours %p and %p.", region.outline, hole);
			continue;
		}
	}
}
Пример #3
0
bool ContourModel::update(vector<vector<Point> > contours,vector<Point2d>& originalPoints, int image_w_half)
{
    
    //step 1: find the larger contours to filter out some noise (area > thresh)
    vector<vector<Point> > largeContours;
    
    int areaThreshold = 130;
    for(int i = 0;i < (int)contours.size();i++)
    {
        vector<Point> currCont = contours.at(i);
        double area = contourArea(contours.at(i));
        if(area > areaThreshold)
        {
            largeContours.push_back(currCont);
        }
    }

    
    //step 2: for each larger contour: find the center of mass and the lane direction to group them
    vector<Point2d> mass_centers;
    vector<Point2d> line_directions;
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        //calculate the line direction for each contour
        Vec4f lineParams;
        fitLine(largeContours.at(i), lineParams, CV_DIST_L2, 0, 0.01, 0.01);
        Point2d lineDirection(lineParams[0],lineParams[1]);
        line_directions.push_back(lineDirection);
        
        //calculate the mass center for each contour
        vector<Moments> contourMoments;
        Moments currMoments = moments(largeContours.at(i));
        double x_cent = currMoments.m10 / currMoments.m00;
        double y_cent = currMoments.m01 / currMoments.m00;
        Point2d mass_cent(x_cent,y_cent);
        mass_centers.push_back(mass_cent);    
    }

    //assert these vectors have same length:
    if(largeContours.size() != mass_centers.size())cout << "ERROR in ContourModel: massCenters.size != largeContours.size()" << endl;
    if(largeContours.size() != line_directions.size())cout << "ERROR in ContourModel: massCenters.size != largeContours.size()" << endl;

    //step 3: create the "mergeList": store for each contour weather it wants to merge with another one
    vector<vector<int> > mergelist;
    //merge contours based on center of mass and line direction
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        vector<int> mergeWishes;
        
        Point2d currCenter = mass_centers.at(i);
        Point2d currDirection = line_directions.at(i);
        
        for(int j = i+1;j < (int)largeContours.size();j++)
        {
            Point2d compCenter = mass_centers.at(j);
            Point2d compDirection = line_directions.at(j);
            
            bool wantMerge = mergeContours(currCenter, currDirection, compCenter, compDirection);
            
            if(wantMerge)mergeWishes.push_back(j);
        }
        
        mergelist.push_back(mergeWishes);
    }

    //step 4: use the mergeList to create the final_mergelist which looks as follows:
    //[ [0,2,5] [3] [1] [4,6]] telling which contours should be merged together
    
    vector<vector<int> > final_mergelist;
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        vector<int> temp;
        temp.push_back(i);
        final_mergelist.push_back(temp);
    }
    
    for(int i = 0;i < (int)largeContours.size();i++)
    {
        vector<int>* containerToPushTo = NULL;
        
        //step 1: find the container the contour i is in - note that this will always succeed so containerToPushTo wont stay NULL
        for(int j = 0;j < (int)final_mergelist.size();j++)
        {
            vector<int>* currContainer;
            currContainer = &final_mergelist.at(j);
            for(int k = 0;k < (int)final_mergelist.at(j).size();k++)
            {
                if(final_mergelist.at(j).at(k) == i)
                {
                    containerToPushTo = currContainer;
                }
            }
        }
        
        //step2: for each element to push: make sure it appears in the container
        for(int j = 0;j < (int)mergelist.at(i).size();j++)
        {
            int elemToMerge = mergelist.at(i).at(j);
            
            //if elemToMerge already appears in containerToPushTo => do nothing
            bool alreadyInContainer = false;
            for(int k = 0;k < (int)containerToPushTo->size();k++)
            {
                if(containerToPushTo->at(k) == elemToMerge)
                    alreadyInContainer = true;
            }
            
            //not inside: push the element and delete it from the old vector it was in
            if(!alreadyInContainer)
            {
                
                //delete it from the old container!!
                for(int k = 0;k < (int)final_mergelist.size();k++)
                {
                    for(int l = 0;l < (int)final_mergelist.at(k).size();l++)
                    {
                        //DEBUG IFS - ERASE LATER
                        if(k < 0 || k >= (int)final_mergelist.size())cout << "OVERFLOW IN 159::ContourModel" << endl;
                        if(l < 0 || l >= (int)final_mergelist.at(k).size())cout << "OVERFLOW IN 160::ContourModel" << endl;

                        if(final_mergelist.at(k).at(l) == elemToMerge)
                        {
                            //DEBUG IF- ERASE LATER
                            if(l < 0 || l >= (int)final_mergelist.at(k).size()) cout << "ERROR ContourModel 162" << endl;
                            final_mergelist.at(k).erase(final_mergelist.at(k).begin()+l);
                        }
                    }
                }
                
                //add it in the new container
                containerToPushTo->push_back(elemToMerge);
            }
            
        }
        
    }
    
    
    //step 5: merge the contours together
    vector< vector<vector<Point> > > mergedContours;
    
    for(int i = 0;i < (int)final_mergelist.size();i++)
    {
        vector<vector<Point> > currGrouping;
        for(int j = 0;j < (int)final_mergelist.at(i).size();j++)
        {
            vector<Point> currContour = largeContours.at(final_mergelist.at(i).at(j));
            currGrouping.push_back(currContour);
        }
        if(currGrouping.size() > 0)mergedContours.push_back(currGrouping);
        
    }


    //TRY TO FIND THE MIDDLE LANE

    vector<vector<Point> >          singleContours;
    vector<vector<vector<Point> > > multipleContours;

    for(int i = 0;i < (int)mergedContours.size();i++)
    {        
        vector<vector<Point> > currContGroup = mergedContours.at(i);
        if(currContGroup.size() == 1) singleContours.push_back(currContGroup.at(0));
        else if(currContGroup.size() > 1) multipleContours.push_back(currContGroup);                
    }

    //in this situation there is actually a chance to apply the middle lane extraction, otherwise the old procedure is applied
    if(multipleContours.size() == 1 && singleContours.size() <= 2 && singleContours.size() > 0)
    {

        //sort single contours by area
        std::sort(singleContours.begin(),singleContours.end(),acompareCont);
        vector<Point> largestSingleContour = singleContours.at(singleContours.size()-1);
        double areaLargestSingle = contourArea(largestSingleContour);

        vector<vector<Point> > middleContour = multipleContours.at(0);
        double areaMiddle = 0;
        bool validMid = true;
        for(int i = 0;i < (int)middleContour.size();i++)
        {
            double areaCurr = contourArea(middleContour.at(i));
            if(areaCurr > areaLargestSingle/2.0){
                validMid = false;
            }
            areaMiddle += contourArea(middleContour.at(i));
        }


        //if both contours have a certain size
        if(areaLargestSingle > 120 && areaMiddle > 120)
        {
            //MIDDLE LANE AND OTHER LANE FOUND => RETURN THE ESTIMATE

            //first argument will be the middle lane
            //second argument will be the other larger lane
            vector<vector<Point2d> > nicelyGroupedPoints;

            //1) --- MIDDLE LANE ---
            vector<Point2d> temp_result;
            for(int i = 0;i < (int)middleContour.size();i++)
            {
                vector<Point> currCont = middleContour.at(i);
                Rect bound = boundingRect(currCont);

                //visit every point in the bounding rect
                for(int y = bound.y;y < bound.y+bound.height;y++)
                {
                    for(int x = bound.x;x < bound.x+bound.width;x++)
                    {
                        if(pointPolygonTest(currCont, Point(x,y), false) >= 0)
                        {
                            temp_result.push_back(Point2d(x-image_w_half,y));
                        }
                    }
                }

            }

            nicelyGroupedPoints.push_back(temp_result);

            //2) --- OTHER LANE ---

            vector<Point2d> temp_result2;

            Rect bound = boundingRect(largestSingleContour);

            //visit every point in the bounding rect
            for(int y = bound.y;y < bound.y+bound.height;y++)
            {
                for(int x = bound.x;x < bound.x+bound.width;x++)
                {
                    if(pointPolygonTest(largestSingleContour, Point(x,y), false) >= 0)
                    {
                        temp_result2.push_back(Point2d(x-image_w_half,y));
                    }
                }
            }


            if(validMid)
            {
                nicelyGroupedPoints.push_back(temp_result2);
                points = nicelyGroupedPoints;
                return true; //middle lane estimate provided
            }
        }
    }

    //MIDDLE LANE WAS NOT FOUND



    //step 6: get the final result: the grouped points matching the contours
    //need to perform a inside contour check within the bounding rectangle of the contour for
    //each point in the bounding rectangle
    vector<vector<Point2d> > nicelyGroupedPoints;

    for(int i = 0;i < (int)mergedContours.size();i++)
    {
        vector<Point2d> temp_result;
        for(int j = 0;j < (int)mergedContours.at(i).size();j++)
        {
            vector<Point> currContour = mergedContours.at(i).at(j);
            Rect bound = boundingRect(currContour);

            //visit every point in the bounding rect
            for(int y = bound.y;y < bound.y+bound.height;y++)
            {
                for(int x = bound.x;x < bound.x+bound.width;x++)
                {
                    if(pointPolygonTest(currContour, Point(x,y), false) >= 0)
                    {
                        temp_result.push_back(Point2d(x-image_w_half,y));
                    }
                }
            }
        }

        if(temp_result.size() > 0)
        {
            nicelyGroupedPoints.push_back(temp_result);
        }
    }


    /*
    //step 6 (alternative): get the final result: the grouped points matching the contours
    //need to perform a inside contour check for the input points if in boundary rectangle of the contour
    vector<vector<Point2d> > nicelyGroupedPoints;

    for(int i = 0;i < mergedContours.size();i++)
    {

        vector<Point2d> temp_result;
        for(int j = 0;j < mergedContours.at(i).size();j++)
        {
            vector<Point> currContour = mergedContours.at(i).at(j);
            Rect bound = boundingRect(currContour);

            for(int k = 0;k < originalPoints.size();k++)
            {
                //check if within the contour:
                if(pointPolygonTest(currContour, originalPoints.at(k), false) >= 0)
                {
                    temp_result.push_back(Point2d(originalPoints.at(k).x-image_w_half, originalPoints.at(k).y));
                }
            }
        }

        if(temp_result.size() > 0)
        {
            nicelyGroupedPoints.push_back(temp_result);
        }
    }

    */


    points = nicelyGroupedPoints;
    return false; //everything as usual, no further information
}