机器视觉标定课设VS(MFC)+OPENCV

使用方法:创建win32空项目(不是控制台),右击项目选属性--常规--MFC--的使用--共享DLL中,然后导入下面十个文件

一、transform.h

#pragma once
#ifndef TRANSFORM_H
#define TRANSFORM_H
#endif // TRANSFORM_H
void DoubleToString(double xx, int n, char* ans);

二、transform.cpp

#include<stdio.h>
#include<math.h>
void DoubleToString(double xx, int n, char* ans) {
	int base = pow(10, n);
	double yy = xx*base;
	int y = (int)yy;
	y %= base;
	int x = (int)xx;
	//cout<<x<<' '<<y<<endl;
	int idx = 0;
	if (y == 0)ans[idx++] = '0';
	while (y>0) {
		ans[idx++] = '0' + y % 10;
		y /= 10;
	}
	ans[idx++] = '.';
	if (x == 0)ans[idx++] = '0';
	while (x>0) {
		ans[idx++] = '0' + x % 10;
		x /= 10;
	}
	//cout<<ans[7]<<ans[6]<<ans[5]<<ans[4]<<ans[3]<<ans[2]<<ans[1]<<ans[0]<<endl;
	idx--;
	for (int i = 0; i <= idx / 2; i++) {
		char tmp = ans[i];
		ans[i] = ans[idx - i];
		ans[idx - i] = tmp;
		//cout<<ans[7]<<ans[6]<<ans[5]<<ans[4]<<ans[3]<<ans[2]<<ans[1]<<ans[0]<<endl;
	}
	ans[++idx] = '\0';
	//printf("%s\n",ans);
}

三、measure_simple.h

#pragma once
#ifndef MEASURE_SIMPLE_H
#define MEASURE_SIMPLE_H
#endif // MEASURE_SIMPLE_H
#include<opencv2/opencv.hpp>
using namespace cv;
void measure_simple(double &proportion);
void ImgSkeletonization(Mat &input_src, Mat &output_dst, int number = 20);//@param  number :表示水平方向和垂直方向上“细化的次数”
void ImgSkeletonization_H(Mat &input_src, int *search_arr);//水平方向细化
void ImgSkeletonization_V(Mat &input_src, int *search_arr);//垂直方向细化

四、measure_simple.cpp

#include<opencv2/opencv.hpp>
#include"transform.h"
#include "measure_simple.h"
using namespace std;
using namespace cv;
static int video_flag = 0;
static void on_mouse(int event, int x, int y, int flags, void*) {
	if (event == EVENT_LBUTTONDOWN)
		if (video_flag == 0)
			video_flag++;
}
void measure_simple(double &proportion) {
	Mat frame;
	namedWindow("frame");
	VideoCapture capture(0);
	setMouseCallback("frame", on_mouse);
	video_flag = 0;
	while (video_flag == 0) {
		waitKey(30);
		capture >> frame;
		imshow("frame", frame);
	}
	imwrite("F:/src1.jpg", frame);
	Mat src = imread("F:/src1.jpg", 0);
	threshold(src, src, 100, 255, 0);
	Mat dst; ImgSkeletonization(src, dst, 30);
	src = dst.clone();
	int a = 10, b = 10, c = 10, d = 10;
	for (int i = 60; i<420; i++) {
		for (int j = 1; j<640; j++) {
			if (src.at<uchar>(i, j) == 0) {
				a = j;
				b = i;
				break;
			}
		}
		if (a != 10)break;
	}
	for (int i = 420; i>60; i--) {
		for (int j = 639; j>0; j--) {
			if (src.at<uchar>(i, j) == 0) {
				c = j;
				d = i;
				break;
			}
		}
		if (c != 10)break;
	}
	//circle(src, Point2i(a, b), 10, Scalar::all(0));
	//circle(src, Point2i(c, d), 10, Scalar::all(0));
	//imshow("src", src);
	circle(frame, Point2i(a, b), 10, Scalar::all(0));
	circle(frame, Point2i(c, d), 10, Scalar::all(0));
	proportion = 10 / sqrt((a - c)*(a - c) + (b - d)*(b - d)); char ppp[20]; DoubleToString(proportion, 2, ppp);
	//cout << '(' << a << ',' << b << ')' << ',' << '(' << c << ',' << d << ')' << ',' << proportion << "mm/pix" << endl;
	putText(frame, ppp, Point(100, 100), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
	putText(frame, "mm/pix", Point(250, 100), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
	imshow("frame", frame);
	waitKey(0);
	destroyAllWindows();
}
void ImgSkeletonization(Mat &input_src, Mat & output_dst, int number) {
	output_dst = input_src.clone();
	int search_array[] = { 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
		1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
		0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
		1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
		1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
		1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,\
		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
		0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
		1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
		0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
		1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
		1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
		1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
		1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,\
		1,1,0,0,1,1,1,0,1,1,0,0,1,0,0,0 };
	for (size_t i = 0; i < number; i++) {
		ImgSkeletonization_H(output_dst, &search_array[0]);
		ImgSkeletonization_V(output_dst, &search_array[0]);

	}
}
void ImgSkeletonization_H(Mat &input_src, int *search_arr) {
	int h = input_src.rows;
	int w = input_src.cols;
	bool NEXT = true;
	for (size_t j = 1; j < w - 1; j++) {//注意边界问题!!!!!!
		for (size_t i = 1; i < h - 1; i++) {
			if (!NEXT)
				NEXT = true;
			else {
				int judge_value;
				if (1 <i < h - 1)
					judge_value = input_src.at<uchar>(i - 1, j) + input_src.at<uchar>(i, j) + input_src.at<uchar>(i + 1, j);
				else
					judge_value = 1;
				if (input_src.at<uchar>(i, j) == 0 && judge_value != 0) {
					int a[9] = { 1,1,1,1,1,1,1,1,1 };
					for (size_t m = 0; m < 3; m++) {
						for (size_t n = 0; n < 3; n++) {
							if ((0 <= (i - 1 + m) < h) && (0 <= (j - 1 + n) < w) && input_src.at<uchar>(i - 1 + m, j - 1 + n) == 0)
								a[m * 3 + n] = 0;
						}
					}
					int sum_value = a[0] * 1 + a[1] * 2 + a[2] * 4 + a[3] * 8 + a[5] * 16 + a[6] * 32 + a[7] * 64 + a[8] * 128;
					input_src.at<uchar>(i, j) = search_arr[sum_value] * 255;
					if (search_arr[sum_value] == 1)
						NEXT = false;
				}
			}
		}
	}
}
void ImgSkeletonization_V(Mat &input_src, int *search_arr) {
	int h = input_src.rows;
	int w = input_src.cols;
	bool NEXT = true;
	for (size_t i = 1; i < h - 1; i++) {//注意边界问题!!!!!!
		for (size_t j = 1; j < w - 1; j++) {
			if (!NEXT)
				NEXT = true;
			else {
				int judge_value;
				if (1 < j <w - 1)
					judge_value = input_src.at<uchar>(i, j - 1) + input_src.at<uchar>(i, j) + input_src.at<uchar>(i, j + 1);
				else
					judge_value = 1;
				if (input_src.at<uchar>(i, j) == 0 && judge_value != 0) {
					int a[9] = { 1,1,1,1,1,1,1,1,1 };
					for (size_t m = 0; m < 3; m++) {
						for (size_t n = 0; n < 3; n++) {
							if ((0 <= (i - 1 + m) < h) && (0 <= (j - 1 + n) < w) && input_src.at<uchar>(i - 1 + m, j - 1 + n) == 0)
								a[m * 3 + n] = 0;
						}
					}
					int sum_value = a[0] * 1 + a[1] * 2 + a[2] * 4 + a[3] * 8 + a[5] * 16 + a[6] * 32 + a[7] * 64 + a[8] * 128;
					input_src.at<uchar>(i, j) = search_arr[sum_value] * 255;
					if (search_arr[sum_value] == 1)
						NEXT = false;
				}
			}
		}
	}
}

五、measure_circle.h

#pragma once
#ifndef MEASURE_CIRCLE_H
#define MEASURE_CIRCLE_H
#endif // MEASURE_CIRCLE_H
void measure_circle(double p);

六、measure_circle.cpp

#include<opencv2/opencv.hpp>
#include"transform.h"
#include<vector>
using namespace std;
using namespace cv;
void measure_circle(double p) {
	Mat frame; int key;
	namedWindow("frame");
	VideoCapture capture(0);
	while (1) {
		key = waitKey(30);
		if (key == ' ')break;
		capture >> frame;
		imshow("frame", frame);
	}
	imwrite("F:/src2.jpg", frame);
	Mat src = imread("F:/src2.jpg", 0);
	GaussianBlur(src, src, Size(9, 9), 2, 2);
	vector<Vec3f>circles;
	HoughCircles(src, circles, HOUGH_GRADIENT, 1.1, 100, 200, 100, 0, 0);
	for (size_t i = 0; i<circles.size(); i++) {
		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
		int radiu = cvRound(circles[i][2]);
		circle(frame, center, 3, Scalar(0, 255, 0), -1, 8, 0);
		circle(frame, center, radiu, Scalar(155, 50, 255), 3, 8, 0);
		double radius = radiu*p;char rrr[20]="0";DoubleToString(radius, 2, rrr);
		//cout << '(' << center.x << ',' << center.y << ") " << radiu << "pix " << radiu*p << "mm" << endl;
		putText(frame, rrr, Point(100, 100), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
		putText(frame, "mm", Point(250, 100), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
	}
	//if (circles.size() == 0)cout << 0 << endl;
	imshow("frame", frame);
	waitKey(0);
	destroyAllWindows();
}

七、measure_rectangle.h

#pragma once
#ifndef MEASURE_RECTANGLE_H
#define MEASURE_RECTANGLE_H
#endif // MEASURE_RECTANGLE_H
void measure_rectangle(double p);

八、measure_rectangle.cpp

#include<opencv2/opencv.hpp>
#include"transform.h"
#include<vector>
using namespace std;
using namespace cv;
void measure_rectangle(double p) {
	Mat frame; int key;
	namedWindow("frame");
	VideoCapture capture(0);
	while (1) {
		key = waitKey(30);
		if (key == ' ')break;
		capture >> frame;
		imshow("frame", frame);
	}
	imwrite("F:/src3.jpg", frame);
	Mat src = imread("F:/src3.jpg", 0);
	vector<Point2f> corners;
	goodFeaturesToTrack(src,//输入图像
		corners,//检测到的角点的输出向量
		4,//角点的最大数量
		0.01,//角点检测可接受的最小特征值
		10,//角点之间的最小距离
		Mat(),//感兴趣区域
		3,//计算导数自相关矩阵时指定的邻域范围
		false,//不使用Harris角点检测
		0.04);//权重系数
	double dis[4], min_dis = 100000, mid_dis = 100000; RNG g_rng(12345);
	for (unsigned long long i = 0; i < corners.size(); i++) {
		cout << corners[i].x << ' ' << corners[i].y << endl;
		circle(frame, corners[i], 4, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)), -1, 8, 0);
		if (i == 0)continue;
		dis[i] = sqrt((corners[i].x - corners[0].x)*(corners[i].x - corners[0].x) + (corners[i].y - corners[0].y)*(corners[i].y - corners[0].y));
		if (dis[i]<min_dis) { mid_dis = min_dis; min_dis = dis[i]; }
		else if (dis[i]<mid_dis)mid_dis = dis[i];
	}
	double length = mid_dis*p; char lll[20]; DoubleToString(length, 2, lll);
	double width = min_dis*p; char www[20]; DoubleToString(width, 2, www);
	//cout << "length: " << mid_dis << "pix," << length << "mm" << endl;
	//cout << "width: " << min_dis << "pix," << width << "mm" << endl;
	putText(frame, lll, Point(50, 50), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
	putText(frame, "mm", Point(200, 50), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
	putText(frame, www, Point(50, 100), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
	putText(frame, "mm", Point(200, 100), FONT_HERSHEY_PLAIN, 3, Scalar::all(0));
	imshow("frame", frame);
	waitKey(0);
	destroyAllWindows();
}

九、main.h

#include<afxwin.h>					//main头文件
class MyApp:public CWinApp {		//CWinApp应用程序类
public:
	virtual BOOL InitInstance();	//程序入口
}; 
class MyFrame :public CFrameWnd {	//窗口框架类
public:
	MyFrame();						//构造函数
	DECLARE_MESSAGE_MAP()			//声明宏 提供消息映射机制
	afx_msg void OnLButtonDown(UINT, CPoint);	//鼠标左键消息响应函数
	afx_msg void OnChar(UINT, UINT, UINT);		//键盘消息响应函数
	afx_msg void OnPaint();						//绘画消息响应函数
};

十、main.cpp

#include "main.h"				//必须滴,千丝万缕的关系
#include "measure_simple.h"		//为了调用标定函数
#include "measure_circle.h"		//为了调用测圆函数
#include "measure_rectangle.h"	//为了调用测矩函数
MyApp app;						//全局应用程序对象,有且仅有一个
BOOL MyApp::InitInstance(){		//程序入口
	MyFrame* frame = new MyFrame;//创建窗口
	frame->ShowWindow(SW_SHOWNORMAL);	//显示
	frame->UpdateWindow();				//更新
	m_pMainWnd = frame;			//保存指向应用程序的主窗口的指针
	return TRUE;				//返回正常初始化
}
BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)	//分界宏上界
	ON_WM_LBUTTONDOWN()					//鼠标左键按下
	ON_WM_CHAR()						//键盘按键按下
	ON_WM_PAINT()						//绘图宏
END_MESSAGE_MAP()						//分界宏下界
MyFrame::MyFrame(){						//构造函数,就是应用程序创建窗口
	Create(NULL, TEXT("mfc"));
}
void MyFrame::OnLButtonDown(UINT, CPoint point){	//按下鼠标左键的响应事件(坐标在CPoint point传入)
	double proportion = 1.0;						//定义比例
	if (point.x > 100 && point.x < 300 && point.y>100 && point.y < 200) measure_simple(proportion);		//标定比例
	if (point.x > 100 && point.x < 300 && point.y>300 && point.y < 400) measure_circle(proportion);		//测量半径
	if (point.x > 100 && point.x < 300 && point.y>500 && point.y < 600) measure_rectangle(proportion);	//测量长宽
}
void MyFrame::OnChar(UINT key, UINT, UINT){								//键盘消息响应函数(键值在UINT key传入)
	CString str;str.Format(TEXT("%c"), key);MessageBox(str);			//CString形式显示对话框
	TCHAR buf[1024]; wsprintf(buf,TEXT("%c"), key); MessageBox(buf);	//TCHAR形式显示对话框
}
void MyFrame::OnPaint(){				//绘画消息响应函数(理论上是应该加定时器刷新的,参考JAVA坦克大战多线程)
	CPaintDC dc(this);					//在CDC里找其他能画的图形
	dc.Ellipse(100, 100, 300, 200);		//给出左上与右下角画内切椭圆(按钮轮廓)
	dc.Ellipse(100, 300, 300, 400);		//给出左上与右下角画内切椭圆(按钮轮廓)
	dc.Ellipse(100, 500, 300, 600);		//给出左上与右下角画内切椭圆(按钮轮廓)
	dc.TextOutW(167, 144, TEXT("measure"));		//画出(按钮标签)
	dc.TextOutW(167, 344, TEXT("circle"));		//画出(按钮标签)
	dc.TextOutW(167, 544, TEXT("retangle"));	//画出(按钮标签)
	POINT pt[2]; pt[0].x = 400, pt[1].y = 100; pt[1].x = 400, pt[1].y = 700;dc.Polyline(pt,2);//给出画直线函数
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值