Beispiel #1
0
// use k-means to reduce color number
MyQuantifiedImage* kmeansQuantification(IplImage* img, int tableSize) {

    // step 1: transfer image to kmeans samples
    int sample_count = img->height * img->width;
    CvMat* samples = cvCreateMat(sample_count, 1, CV_32FC3);
    CvRNG rng = cvRNG(0xffffffff);

    int idx = 0;
    for (int i = 0; i < img->height; i++) {
	for (int j = 0; j < img->width; j++) {
	    cvSet1D(samples, idx++, cvGet2D(img, i, j));
	}
    }
    
    // step 2: apply kmeans;
    CvMat* labels = cvCreateMat(sample_count, 1, CV_32SC1);
    CvMat* centers = cvCreateMat(tableSize, 1, CV_32FC3);
    cvSetZero(labels);
    cvSetZero(centers);
    
    cvKMeans2(samples, tableSize, labels,
	      cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 
			     10, CV_KMEANS_ACC), 
	      CV_KMEANS_ATTEMPTS, &rng,
	      CV_KMEANS_PP_CENTERS, centers, 0); // flag = KMEANS_PP_CENTERS

    // step 3: rebuild the image
    IplImage* quantImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 3);
    CvMat* labelImg = cvCreateMat(img->height, img->width, CV_32SC1);
    cvSetZero(quantImg);
    cvSetZero(labelImg);
    
    idx = 0;
    for (int i = 0; i < img->height; i++) {
	for (int j = 0; j < img->width; j++) {
	    int cluster_idx = labels->data.i[idx++];
	    CvScalar color = cvGet1D(centers, cluster_idx);
	    cvSet2D(quantImg, i, j, color);
	    cvSetReal2D(labelImg, i, j, (double) cluster_idx);
	}
    }

    MyQuantifiedImage* re = malloc(sizeof(MyQuantifiedImage));
    re->labelMat = labelImg;
    re->qImg = quantImg;
    re->tableSize = tableSize;
    
    CvScalar* colorTable = calloc(tableSize, sizeof(CvScalar));
    for (int i = 0; i < tableSize; i++) {
	colorTable[i] = cvGet1D(centers, i);
    }
    re->colorTable = colorTable;


    return re;
}
Beispiel #2
0
/**
 * Method for summing all the rows in a vector to a value of type double.
 *
 * @param src A pointer to a vector to be summed.
 *
 * @return Returns sum of all rows in a vector as a double.
 */
double LibFaceUtils::sumVecToDouble(CvMat* src)
{
    double sum = 0;
    int i;

    for (i = 0; i < src->rows; ++i)
    {
        sum = sum + cvGet1D(src, i).val[0];
    }

    return sum;
}
Beispiel #3
0
/**
 * A method for adding another element to the end of a vector.
 *
 * @param src A pointer to a matrix.
 * @param value Value to be appended to the end.
 *
 * @return Returns a pointer to the new vector.
 */
CvMat* LibFaceUtils::addScalar(CvMat* src, CvScalar value)
{
    CvMat* result = cvCreateMat(src->rows+1,1,src->type);
    int i;

    for (i=0 ; i < src->rows ; ++i)
    {
        cvSet1D(result, i, cvGet1D(src, i));
    }

    cvSet1D(result, src->rows,value);

    return result;
}
Beispiel #4
0
/**
 *  A method for subtrating a vector from a matrix. New matrix is created in process.
 *
 *  @param src1 A pointer to a matrix to be subtracted from.
 *  @param src2 A pointer to a vector to be subtracted.
 *
 *  @return Returns a pointer to the new matrix.
 */
CvMat* LibFaceUtils::subtract(CvMat* src1, CvMat* src2)
{
    int    i, j;
    CvMat* result = cvCreateMat(src1->rows, src1->cols, src1->type);

    for (i = 0 ; i < src1->rows ; ++i)
    {
        for (j=0 ; j < src1->cols ; ++j)
        {
            double value1 = cvGet2D(src1, i, j).val[0];
            double value2 = cvGet1D(src2, i).val[0];
            double res    = value1 - value2;

            cvSet2D(result, i, j, cvScalarAll(res));
        }
    }
    return result;
}
Beispiel #5
0
/**
 * Method for adding an extra column to a matrix. This method makes no checks on validity
 * of the data.
 *
 * @param src A pointer to a matrix to be added to.
 * @param vector A pointer to a vector to be added to the matrix. Needs to have the same number of rows.
 *
 * @return Returns a pointer to the new matrix with added column.
 */
CvMat* LibFaceUtils::combine(CvMat* src, CvMat* vector)
{
    int i, j;
    CvMat* result = cvCreateMat(src->rows, src->cols + 1, src->type);

    for (i = 0; i < src->rows; ++i)
    {
        for (j = 0; j <= src->cols; ++j)
        {
            if (j != src->cols)
                cvSet2D(result, i, j, cvGet2D(src, i, j));
            else
                cvSet2D(result, i, j, cvGet1D(vector, i));
        }
    }

    return result;
}
Beispiel #6
0
void cveGet1D(CvArr* arr, int idx0, CvScalar* value)
{
   *value = cvGet1D(arr, idx0);
}
Beispiel #7
0
int main()
{
    IplImage* img = cvLoadImage("goal_arena.bmp");
    CvSize imgSize = cvGetSize(img);
    IplImage* detected = cvCreateImage(imgSize, 8, 1);
 
    IplImage* imgBlue = cvCreateImage(imgSize, 8, 1);
    IplImage* imgGreen = cvCreateImage(imgSize, 8, 1);
    IplImage* imgRed = cvCreateImage(imgSize, 8, 1);

    cvSplit(img, imgBlue, imgGreen, imgRed, NULL);
    cvAnd(imgGreen, imgBlue, detected);
    cvAnd(detected, imgRed, detected);
    cvErode(detected, detected);
    cvDilate(detected, detected);    // Opening
 
    // cvThreshold(detected, detected, 100, 250, CV_THRESH_BINARY);
    CvMat* lines = cvCreateMat(100, 1, CV_32FC2);
    cvHoughLines2(detected, lines, CV_HOUGH_STANDARD, 1, 0.001, 100);
    // CvMat* lines = cvCreateMat(100, 1, CV_32FC2);
    // cvHoughLines2(detected, lines, CV_HOUGH_STANDARD, 1, 0.001, 100);

    CvPoint left1 = cvPoint(0, 0);
    CvPoint left2 = cvPoint(0, 0);
    CvPoint right1 = cvPoint(0, 0);
    CvPoint right2 = cvPoint(0, 0);
    CvPoint top1 = cvPoint(0, 0);
    CvPoint top2 = cvPoint(0, 0);
    CvPoint bottom1 = cvPoint(0, 0);
    CvPoint bottom2 = cvPoint(0, 0);
 
    int numLines = lines->rows;
    int numTop = 0;
    int numBottom = 0;
    int numLeft = 0;
    int numRight = 0;

    for(int i=0;i<numLines;i++)
    {
    	CvScalar dat = cvGet1D(lines, i);
        double rho = dat.val[0];
        double theta = dat.val[1];
        if(theta==0.0)
            continue;
        double degrees = theta*180.0/(3.1412);
 
        CvPoint pt1 = cvPoint(0, rho/sin(theta));
        CvPoint pt2 = cvPoint(img->width, (-img->width/tan(theta)) + rho/sin(theta));
         if(abs(rho)<50.0)
        {
        	if(degrees>45.0 && degrees<135.0)
            {
            	numTop++;
 
                // The line is vertical and near the top
                top1.x+=pt1.x;
                top1.y+=pt1.y;
 
                top2.x+=pt2.x;
                top2.y+=pt2.y;
            }

            else
            {
                numLeft++;
 
                // The line is vertical and near the left
                left1.x+=pt1.x;
                left1.y+=pt1.y;
 
                left2.x+=pt2.x;
                left2.y+=pt2.y;
            }
        }

        else
        {
            // We're in the right portion
            if(degrees>45.0 && degrees<135.0)
            {
                numBottom++;
 
                //The line is horizontal and near the bottom
                bottom1.x+=pt1.x;
                bottom1.y+=pt1.y;
 
                bottom2.x+=pt2.x;
                bottom2.y+=pt2.y;
            }
            else
            {
                numRight++;
 
                // The line is vertical and near the right
                right1.x+=pt1.x;
                right1.y+=pt1.y;
 
                right2.x+=pt2.x;
                right2.y+=pt2.y;
            }
        }
    }

    left1.x/=numLeft;
    left1.y/=numLeft;
    left2.x/=numLeft;
    left2.y/=numLeft;
 
    right1.x/=numRight;
    right1.y/=numRight;
    right2.x/=numRight;
    right2.y/=numRight;
 
    top1.x/=numTop;
    top1.y/=numTop;
    top2.x/=numTop;
    top2.y/=numTop;
 
    bottom1.x/=numBottom;
    bottom1.y/=numBottom;
    bottom2.x/=numBottom;
    bottom2.y/=numBottom;

    cvLine(img, left1, left2, CV_RGB(255, 0,0), 1);
    cvLine(img, right1, right2, CV_RGB(255, 0,0), 1);
    cvLine(img, top1, top2, CV_RGB(255, 0,0), 1);
    cvLine(img, bottom1, bottom2, CV_RGB(255, 0,0), 1);

    // Next, we need to figure out the four intersection points
    double leftA = left2.y-left1.y;
    double leftB = left1.x-left2.x;
    double leftC = leftA*left1.x + leftB*left1.y;
 
    double rightA = right2.y-right1.y;
    double rightB = right1.x-right2.x;
    double rightC = rightA*right1.x + rightB*right1.y;
 
    double topA = top2.y-top1.y;
    double topB = top1.x-top2.x;
    double topC = topA*top1.x + topB*top1.y;
 
    double bottomA = bottom2.y-bottom1.y;
    double bottomB = bottom1.x-bottom2.x;
    double bottomC = bottomA*bottom1.x + bottomB*bottom1.y;
 
    // Intersection of left and top
    double detTopLeft = leftA*topB - leftB*topA;
    CvPoint ptTopLeft = cvPoint((topB*leftC - leftB*topC)/detTopLeft, (leftA*topC - topA*leftC)/detTopLeft);
 
    // Intersection of top and right
    double detTopRight = rightA*topB - rightB*topA;
    CvPoint ptTopRight = cvPoint((topB*rightC-rightB*topC)/detTopRight, (rightA*topC-topA*rightC)/detTopRight);
 
    // Intersection of right and bottom
    double detBottomRight = rightA*bottomB - rightB*bottomA;
    CvPoint ptBottomRight = cvPoint((bottomB*rightC-rightB*bottomC)/detBottomRight, (rightA*bottomC-bottomA*rightC)/detBottomRight);
 
    // Intersection of bottom and left
    double detBottomLeft = leftA*bottomB-leftB*bottomA;
    CvPoint ptBottomLeft = cvPoint((bottomB*leftC-leftB*bottomC)/detBottomLeft, (leftA*bottomC-bottomA*leftC)/detBottomLeft);

    cvLine(img, ptTopLeft, ptTopLeft, CV_RGB(0,255,0), 5);
    cvLine(img, ptTopRight, ptTopRight, CV_RGB(0,255,0), 5);
    cvLine(img, ptBottomRight, ptBottomRight, CV_RGB(0,255,0), 5);
    cvLine(img, ptBottomLeft, ptBottomLeft, CV_RGB(0,255,0), 5);

    IplImage* imgMask = cvCreateImage(imgSize, 8, 3);
    cvZero(imgMask);
    CvPoint* pts = new CvPoint[4];
    pts[0] = ptTopLeft;
    pts[1] = ptTopRight;
    pts[2] = ptBottomRight;
    pts[3] = ptBottomLeft;
    cvFillConvexPoly(imgMask, pts, 4, cvScalar(255,255,255));
    cvAnd(img, imgMask, img);
 
    cvNamedWindow("Original");
    cvNamedWindow("Detected");
 
    cvShowImage("Original", img);
    cvShowImage("Detected", detected);
    cvWaitKey(0);
 
    return 0;
}
int main()
{
	// Load the image we'll work on
	IplImage* img = cvLoadImage("C:\\goal_arena.jpg");
	CvSize imgSize = cvGetSize(img);

	// This will hold the white parts of the image
	IplImage* detected = cvCreateImage(imgSize, 8, 1);

	// These hold the three channels of the loaded image
	IplImage* imgBlue = cvCreateImage(imgSize, 8, 1);
	IplImage* imgGreen = cvCreateImage(imgSize, 8, 1);
	IplImage* imgRed = cvCreateImage(imgSize, 8, 1);
	cvSplit(img, imgBlue, imgGreen, imgRed, NULL);

	// Extract white parts into detected
	cvAnd(imgGreen, imgBlue, detected);
	cvAnd(detected, imgRed, detected);

	// Morphological opening
	cvErode(detected, detected);
	cvDilate(detected, detected);

	// Thresholding (I knew you wouldn't catch this one... so i wrote a comment here
	// I mean the command can be so decieving at times)
	cvThreshold(detected, detected, 100, 250, CV_THRESH_BINARY);

	// Do the hough thingy
	CvMat* lines = cvCreateMat(100, 1, CV_32FC2);
	cvHoughLines2(detected, lines, CV_HOUGH_STANDARD, 1, 0.001, 100);
	
	// The two endpoints for each boundary line
	CvPoint left1 = cvPoint(0, 0);
	CvPoint left2 = cvPoint(0, 0);
	CvPoint right1 = cvPoint(0, 0);
	CvPoint right2 = cvPoint(0, 0);
	CvPoint top1 = cvPoint(0, 0);
	CvPoint top2 = cvPoint(0, 0);
	CvPoint bottom1 = cvPoint(0, 0);
	CvPoint bottom2 = cvPoint(0, 0);

	// Some numbers we're interested in
	int numLines = lines->rows;
	int numTop = 0;
	int numBottom = 0;
	int numLeft = 0;
	int numRight = 0;

	// Iterate through each line
	for(int i=0;i<numLines;i++)
	{
		// Get the parameters for the current line
		CvScalar dat = cvGet1D(lines, i);
		double rho = dat.val[0];
		double theta = dat.val[1];
		
		if(theta==0.0)
		{
			// This is an obviously vertical line... and we can't approximate it... NEXT
			continue;
		}

		// Convert from radians to degrees
		double degrees = theta*180/(3.1412);
		
		// Generate two points on this line (one at x=0 and one at x=image's width)
		CvPoint pt1 = cvPoint(0, rho/sin(theta));
		CvPoint pt2 = cvPoint(img->width, (-img->width/tan(theta)) + rho/sin(theta));
		
		if(abs(rho)<50)		// Top + left
		{
			if(degrees>45 && degrees<135)	// Top
			{
				numTop++;

				// The line is horizontal and near the top
				top1.x+=pt1.x;
				top1.y+=pt1.y;
			
				top2.x+=pt2.x;
				top2.y+=pt2.y;
			}
			else	// left
			{
				numLeft++;

				//The line is vertical and near the left
				left1.x+=pt1.x;
				left1.y+=pt1.y;
			
				left2.x+=pt2.x;
				left2.y+=pt2.y;
			}
		}
		else // bottom+right
		{
			if(degrees>45 && degrees<135)	// Bottom
			{
				numBottom++;

				//The line is horizontal and near the bottom
				bottom1.x+=pt1.x;
				bottom1.y+=pt1.y;
			
				bottom2.x+=pt2.x;
				bottom2.y+=pt2.y;
			}
			else	// Right
			{
				numRight++;

				// The line is vertical and near the right
				right1.x+=pt1.x;
				right1.y+=pt1.y;
				
				right2.x+=pt2.x;
				right2.y+=pt2.y;
			}
		}
	}

	// we've done the adding... now the dividing to get the "averaged" point
	left1.x/=numLeft;
	left1.y/=numLeft;
	left2.x/=numLeft;
	left2.y/=numLeft;

	right1.x/=numRight;
	right1.y/=numRight;
	right2.x/=numRight;
	right2.y/=numRight;

	top1.x/=numTop;
	top1.y/=numTop;
	top2.x/=numTop;
	top2.y/=numTop;

	bottom1.x/=numBottom;
	bottom1.y/=numBottom;
	bottom2.x/=numBottom;
	bottom2.y/=numBottom;

	// Render these lines onto the image
	cvLine(img, left1, left2, CV_RGB(255, 0,0), 1);
	cvLine(img, right1, right2, CV_RGB(255, 0,0), 1);
	cvLine(img, top1, top2, CV_RGB(255, 0,0), 1);
	cvLine(img, bottom1, bottom2, CV_RGB(255, 0,0), 1);

	// Next, we need to figure out the four intersection points
	double leftA = left2.y-left1.y;
	double leftB = left1.x-left2.x;
	double leftC = leftA*left1.x + leftB*left1.y;

	double rightA = right2.y-right1.y;
	double rightB = right1.x-right2.x;
	double rightC = rightA*right1.x + rightB*right1.y;

	double topA = top2.y-top1.y;
	double topB = top1.x-top2.x;
	double topC = topA*top1.x + topB*top1.y;

	double bottomA = bottom2.y-bottom1.y;
	double bottomB = bottom1.x-bottom2.x;
	double bottomC = bottomA*bottom1.x + bottomB*bottom1.y;

	// Intersection of left and top
	double detTopLeft = leftA*topB - leftB*topA;
	CvPoint ptTopLeft = cvPoint((topB*leftC - leftB*topC)/detTopLeft, (leftA*topC - topA*leftC)/detTopLeft);

	// Intersection of top and right
	double detTopRight = rightA*topB - rightB*topA;
	CvPoint ptTopRight = cvPoint((topB*rightC-rightB*topC)/detTopRight, (rightA*topC-topA*rightC)/detTopRight);

	// Intersection of right and bottom
	double detBottomRight = rightA*bottomB - rightB*bottomA;
	CvPoint ptBottomRight = cvPoint((bottomB*rightC-rightB*bottomC)/detBottomRight, (rightA*bottomC-bottomA*rightC)/detBottomRight);

	// Intersection of bottom and left
	double detBottomLeft = leftA*bottomB-leftB*bottomA;
	CvPoint ptBottomLeft = cvPoint((bottomB*leftC-leftB*bottomC)/detBottomLeft, (leftA*bottomC-bottomA*leftC)/detBottomLeft);

	// Render the points onto the image
	cvLine(img, ptTopLeft, ptTopLeft, CV_RGB(0,255,0), 5);
	cvLine(img, ptTopRight, ptTopRight, CV_RGB(0,255,0), 5);
	cvLine(img, ptBottomRight, ptBottomRight, CV_RGB(0,255,0), 5);
	cvLine(img, ptBottomLeft, ptBottomLeft, CV_RGB(0,255,0), 5);

	// Initialize a mask
	IplImage* imgMask = cvCreateImage(imgSize, 8, 3);
	cvZero(imgMask);

	// Generate the mask
	CvPoint* pts = new CvPoint[4];
	pts[0] = ptTopLeft;
	pts[1] = ptTopRight;
	pts[2] = ptBottomRight;
	pts[3] = ptBottomLeft;
	cvFillConvexPoly(imgMask, pts, 4, cvScalar(255,255,255));

	// Delete anything thats outside the mask
	cvAnd(img, imgMask, img);

	// Show all images in windows
	cvNamedWindow("Original");
	cvNamedWindow("Detected");

	cvShowImage("Original", img);
	cvShowImage("Detected", detected);

	cvWaitKey(0);

	return 0;
}