您的位置:首页 > 运维架构

《OpenCV》Part6 OpenCV3.1.0 用直线拟合图像中的物体

2016-11-21 13:21 363 查看
《OpenCV》Part6 OpenCV3.1.0 用直线拟合图像中的物体

1、先来用几个点来拟合出直线,

示例1:

#include "cv.h"
#include "highgui.h"
#include <math.h>
int main(int argc, char* argv[])
{
IplImage* img = cvCreateImage(cvSize(500, 500), 8, 3);
CvRNG rng = cvRNG(-1); //cvRNG()跟一般的C语言srand()使用方法一样,要先给它一个种子,
//但srand()用到的是unsigned int的32位种子范围,而cvRNG()用的是64位长整数种子。
//初始化CvRNG资料结构,假如seed给0,它将会自动转成-1   cvRNG(64位种子)
cvNamedWindow("fitline", 1);

for (;;)
{
char key;
int i;
int count = cvRandInt(&rng) % 100 + 1; //产生1-100 之间的数
int outliers = count / 5; // 奇异点的个数。0--20 之间的数
printf("count = %d", count);
float a = cvRandReal(&rng) * 200;  // 0~ 199 之间的浮点数 [cvRandReal 浮点型随机数并更新 RNG ,范围在 0..1 之间,不包括 。
float b = cvRandReal(&rng) * 40; //返回0 ~ 39之间的数
float angle = cvRandReal(&rng)*CV_PI;
printf("count = %f", angle);
float cos_a = cos(angle), sin_a = sin(angle);
printf("cos_a = %f", cos_a);

CvPoint pt1, pt2; //直线的两个端点
CvPoint* points = (CvPoint*)malloc(count * sizeof(points[0])); //存放随机产生的点点,数目为count
CvMat pointMat = cvMat(1, count, CV_32SC2, points); //点集, 存储count个随机点points
float line[4]; //输出的直线参数。2D 拟合情况下,它是包含 4 个浮点数的数组 (vx, vy, x0, y0)
//其中 (vx, vy) 是线的单位向量而 (x0, y0) 是线上的某个点
float d, t;
b = MIN(a*0.3, b);

// generate some points that are close to the line
for (i = 0; i < count - outliers; i++)
{
float x = (cvRandReal(&rng) * 2 - 1)*a;
float y = (cvRandReal(&rng) * 2 - 1)*b;
points[i].x = cvRound(x*cos_a - y*sin_a + img->width / 2);
points[i].y = cvRound(x*sin_a + y*cos_a + img->height / 2);
}
// generate "completely off" points
for (; i < count; i++)
{
points[i].x = cvRandInt(&rng) % img->width;
points[i].y = cvRandInt(&rng) % img->height;
}

// find the optimal line 曲线拟合
cvFitLine(&pointMat, CV_DIST_L1, 1, 0.001, 0.001, line);
cvZero(img);

//画出产生的随机分布的点点
for (i = 0; i < count; i++)
cvCircle(img, points[i], 2, i < count - outliers ? CV_RGB(255, 0, 0) : CV_RGB(255, 255, 0), CV_FILLED, CV_AA, 0);

// ... and the long enough line to cross the whole image
d = sqrt((double)line[0] * line[0] + (double)line[1] * line[1]);  //line[0 & 1]存储的是单位向量,所以d=1
//printf("\n %f\n", d);
line[0] /= d;
line[1] /= d;

//画出线段的两个端点(避免线太短,以线上一个随机点向两侧延伸line[0]*t )
t = (float)(img->width + img->height);
pt1.x = cvRound(line[2] - line[0] * t);
pt1.y = cvRound(line[3] - line[1] * t);
pt2.x = cvRound(line[2] + line[0] * t);
pt2.y = cvRound(line[3] + line[1] * t);
cvLine(img, pt1, pt2, CV_RGB(0, 255, 0), 3, CV_AA, 0);

cvShowImage("fitline", img);
key = (char)cvWaitKey(0);
if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
break;
free(points);
}

cvDestroyWindow("fitline");
return 0;
}




2、用椭圆拟合图片中物体
fitellipse.cpp:/********************************************************************************
*
*
* This program is demonstration for ellipse fitting. Program finds
* contours and approximate it by ellipses.
*
* Trackbar specify threshold parametr.
*
* White lines is contours. Red lines is fitting ellipses.
*
*
********************************************************************************/
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
// static void help()
// {
// cout <<
// "\nThis program is demonstration for ellipse fitting. The program finds\n"
// "contours and approximate it by ellipses.\n"
// "Call:\n"
// "./fitellipse [image_name -- Default ../data/fitline.jpg]\n" << endl;
// }
int sliderPos = 70;
Mat image;
void processImage(int, void*);
void drawLine(int, void*);
void huoghLineFind();
int main(int argc, char** argv)
{
//const char* filename = argc == 2 ? argv[1] : (char*)"../data/fitline.jpg";
const char* filename = "fitline.jpg";//laser6.jpg//fitline.jpg
image = imread(filename, 0);
if (image.empty())
{
cout << "Couldn't open image " << filename << "\nUsage: fitellipse <image_name>\n";
return 0;
}
imshow("source", image);
namedWindow("result", 1);
// Create toolbars. HighGUI use.
createTrackbar("threshold", "result", &sliderPos, 255, processImage);
processImage(0, 0);
drawLine(0, 0);

// Wait for a key stroke; the same function arranges events processing
waitKey();
return 0;
}
// Define trackbar callback functon. This function find contours,
// draw it and approximate it by ellipses.
void processImage(int /*h*/, void*)
{
vector<vector<Point> > contours;
Mat bimage = image >= sliderPos;
findContours(bimage, contours, RETR_LIST, CHAIN_APPROX_NONE);
Mat cimage = Mat::zeros(bimage.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++)
{
size_t count = contours[i].size();
if (count < 6)
continue;
Mat pointsf;
Mat(contours[i]).convertTo(pointsf, CV_32F);
RotatedRect box = fitEllipse(pointsf);
if (MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height) * 30)
continue;
drawContours(cimage, contours, (int)i, Scalar::all(255), 1, 8);
ellipse(cimage, box, Scalar(0, 0, 255), 1, LINE_AA);
ellipse(cimage, box.center, box.size*0.5f, box.angle, 0, 360, Scalar(0, 255, 255), 1, LINE_AA);
Point2f vtx[4];
box.points(vtx);
for (int j = 0; j < 4; j++)
line(cimage, vtx[j], vtx[(j + 1) % 4], Scalar(0, 255, 0), 1, LINE_AA);
}
imshow("result", cimage);
}

void drawLine(int, void*)
{
namedWindow("drawLine", 2);
vector<vector<Point> > contours;
Mat bimage = image >= sliderPos;
findContours(bimage, contours, RETR_LIST, CHAIN_APPROX_NONE);
Mat cimage = Mat::zeros(bimage.size(), CV_8UC3);

for (size_t i = 0; i < contours.size(); i++)
{
size_t count = contours[i].size();
if (count < 6)
continue;
Mat pointsf;
Mat(contours[i]).convertTo(pointsf, CV_32F);
RotatedRect box = fitEllipse(pointsf);
if (MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height) * 30)
continue;

//int row = cimage.cols;
//int col = cimage.rows;
//float line[4]; //输出的直线参数。2D 拟合情况下,它是包含 4 个浮点数的数组 (vx, vy, x0, y0)
//其中 (vx, vy) 是线的单位向量而 (x0, y0) 是线上的某个点
//Point2f vtx[4];
//box.points(vtx);
//Mat pointMat = Mat(1, count, CV_32SC2, vtx); //点集, 存储count个随机点points
//cvFitLine(&pointMat, DIST_L1, 1, 0.001, 0.001,line);

//int lefty = int((-x*vy / vx) + y);
//int righty = int(((cols - x)*vy / vx) + y);
//box结构中包含椭圆的中心坐标, 将椭圆数据从浮点转化为整数表示
//Point x = cvRound(box.center.x);
//Point y = cvRound(box.center.y);
//line(cimage,Point(0,0),(x,y),Scalar(255,255,0),2,LINE_AA);

Point2f vtx[4];
box.points(vtx);
for (int j = 0; j < 4; j++)
//int j = 4;
line(cimage, (vtx[j] + vtx[(j + 3) % 4]) / 2, (vtx[(j + 1) % 4] + vtx[(j + 2) % 4])/2, Scalar(225, 10, 10), 1, LINE_AA);

}
imshow("drawLine", cimage);

}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: