仪表识别形状匹配

#include “stdafx.h”
#include “opencv2/imgproc/imgproc_c.h”
#include “opencv2/imgproc/imgproc.hpp”
#include “opencv2/highgui/highgui.hpp”
#include “opencv2/opencv.hpp”
#include “windows.h”
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include
#include
#include
#include
#include

#define PI 3.14159265

using namespace cv;
using namespace std;
#pragma warning(disable:4996)
static RNG rng(12345);

bool GreaterRadius(Vec3f a, Vec3f b)
{
return (a[2] > b[2]);
}
bool GreaterSize(vector a, vector b)
{
return (a.size() > b.size());
}

Mat rgbHSVrgb(Mat srcImg)
{
Mat tmpHsvImg;
Mat pointerImg;
//将RGB颜色空间转换为HSV颜色空间
cvtColor(srcImg, tmpHsvImg, COLOR_BGR2HSV); //CV_BGR2YCrCb
//int minH = 84; //26
//int maxH = 150; //34
//int minS = 5; //
//int maxS = 255;
//int minV = 92; //200
//int maxV = 255;
int minH = 0; //26
int maxH = 360; //34
int minS = 0; //
int maxS = 255;
int minV = 0; //200
int maxV = 155;
//int minH = 0; //26
//int maxH = 360; //34
//int minS = 0; //
//int maxS = 255;
//int minV = 0; //200
//int maxV = 46;
inRange(tmpHsvImg, Scalar(minH, minS, minV), Scalar(maxH, maxS, maxV), pointerImg);
pointerImg.convertTo(pointerImg, CV_8UC3, 255.0, 0);
return pointerImg;
}

vector findTargetContour(Vec3f cir, vector<vector> curContour)
{
vector tmpContour;
Point center(cvRound(cir[0]), cvRound(cir[1]));
float radius = cvRound(cir[2]);

int width = radius / 2;
int height = radius / 2;
int minx = (int)(center.x - width / 2);
int miny = (int)(center.y - width / 2);

Rect rect(minx, miny, width, height);
vector<int> verCount;
for (int i = 0; i < curContour.size(); i++)
{
	int curCount = 0;
	for (int j = 0; j < curContour[i].size(); j++)
	{
		if (rect.contains(curContour[i][j]))
		{
			curCount++;
		}
	}
	verCount.push_back(curCount);
}
int maxPosition = max_element(verCount.begin(), verCount.end()) - verCount.begin();
return curContour[maxPosition];

}

cv::Mat convert2Bbinary(cv::Mat image)
{
//图像高宽
int nHeight = image.rows;
int nWidth = image.cols;
//创建灰度图像,初始化
Mat TargImg;
TargImg.create(nHeight, nWidth, CV_8UC1);
TargImg = Scalar::all(255);

int threRelativeVal = 40; //较差阈值
int threBlackVal = 100; //像素绝对值阈值
						//遍历图像像素,刻度、指针和数字为黑,背景为白
for (int j = 0; j < nHeight; j++)
{
	for (int i = 0; i < nWidth; i++)
	{
		//获取每个像素的rgb值
		int b = image.at<Vec3b>(cv::Point(i, j))[0];
		int g = image.at<Vec3b>(cv::Point(i, j))[1];
		int r = image.at<Vec3b>(cv::Point(i, j))[2];
		//目标找到,开始遍历;双判断条件,一是像素rgb值差值、二是像素绝对值
		//if (abs(b - r) < threRelativeVal&&abs(b - g) < threRelativeVal&&abs(g - b) < threRelativeVal&&b < threBlackVal
		//	&&r < threBlackVal&&g < threBlackVal)
		if (r < 255 || b < 255 || g < 255)
		{
			TargImg.at<uchar>(cv::Point(i, j)) = 0;
		}
	}
}
return TargImg;

}

vector<vector> getRawPointerBoundary(Mat tmpSrcImg)
{
Mat pointerImg = rgbHSVrgb(tmpSrcImg);//将3通道图像转化为二值图像
//Mat pointerImg = convert2Bbinary(tmpSrcImg);
vector<vector> contours;
vector hierarchy;
Mat ptrBinaryImage = convertColorToBinaryImage(pointerImg);
findContours(pointerImg, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));//发现轮廓
pointerImg.release();
return contours;
}
vector<vector> getTarPointerBoundary(Mat tmpSrcImg)
{
Mat pointerImg = rgbHSVrgb(tmpSrcImg);//将3通道图像转化为二值图像
//Mat pointerImg = convert2Bbinary(srcImg);
vector<vector> contours;
vector hierarchy;
Mat ptrBinaryImage = convertColorToBinaryImage(pointerImg);
findContours(pointerImg, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));//发现轮廓
//std::sort(contours.begin(), contours.end(), GreaterSize);//对边界进行排序
pointerImg.release();
//vector<vector> needle;
//vector tmpNeedle;
//tmpNeedle = findTargetContour(circles[0], contours);//找到指针边界
//needle.push_back(tmpNeedle);
return contours;
}

vector<vector> matchTargetShape(vector rawBoundary, vector<vector> curBoundarys)
{
vector matVal;

//cout << "目标容器大小:" << rawBoundary.size()<<endl;
int rawCount = rawBoundary.size();

for (int i=0;i< curBoundarys.size();i++)
{
	if (curBoundarys[i].size()<25)
	{
		matVal.push_back(99999);
	}
	else
	{
		float tmpMatVal = matchShapes(curBoundarys[i], rawBoundary, CV_CONTOURS_MATCH_I2, 1.0);//进行轮廓匹配
		matVal.push_back(tmpMatVal);
	}
}
int minPosition = min_element(matVal.begin(), matVal.end()) - matVal.begin();
int maxPosition = max_element(matVal.begin(), matVal.end()) - matVal.begin();
vector<vector<Point>> tarBoundary;
tarBoundary.push_back(curBoundarys[minPosition]);

return tarBoundary;

}

vector<vector> matchTargetSize(vector rawBoundary, vector<vector> curBoundarys)
{
vector matVal;
//cout << “目标容器大小:” << rawBoundary.size() << endl;
int rawCount = rawBoundary.size();

for (int i = 0; i < curBoundarys.size(); i++)
{
	int curCount = curBoundarys[i].size();
	int res = abs(curCount - rawCount);
	matVal.push_back(res);
}
int minPosition = min_element(matVal.begin(), matVal.end()) - matVal.begin();
int maxPosition = max_element(matVal.begin(), matVal.end()) - matVal.begin();
vector<vector<Point>> tarBoundary;
tarBoundary.push_back(curBoundarys[minPosition]);
return tarBoundary;

}

Vec3f getCircleParam(Mat tmpSrcGray)
{
//检测仪表外接圆
vector circles;
float radius = tmpSrcGray.rows / 3.0;
float minRad = tmpSrcGray.rows / 3.0;
float maxRad = tmpSrcGray.rows / 2.0;
HoughCircles(tmpSrcGray, circles, CV_HOUGH_GRADIENT, 1, radius, 200, 100, minRad, maxRad);
std::sort(circles.begin(), circles.end(), GreaterRadius);//找最大的半径,即是仪表盘
return circles[0];
}

int main()
{
Mat rawImg = imread(“HSV_inRange1.jpg”);
//模板指针链表
vector<vector> templatePointer = getRawPointerBoundary(rawImg);
int nCount = templatePointer.size();
for (int i=0;i<nCount;i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(rawImg, templatePointer, i, color, 1, 8, vector(), 0, Point());
}

imshow("模板指针", rawImg);
//rawImg.release();

Mat srcImg = imread("12.jpg");
blur(srcImg, srcImg, Size(3, 3));
//查看图像通道数量
//int nChannel = srcImg.channels();
//cout << nChannel << endl;
//彩色图像灰度化
Mat srcGray;
cvtColor(srcImg, srcGray, COLOR_BGR2GRAY);
//srcImg.release();
//图像仪表圆盘检测和圆心定位参数
Vec3f cirParam = getCircleParam(srcGray);
srcGray.release();
//图像仪表指针检测
vector<vector<Point>> tarPointers= getTarPointerBoundary(srcImg);

//vector<vector<Point>> resPointer = matchTargetSize(templatePointer[0],tarPointers);
vector<vector<Point>> resPointer = matchTargetShape(templatePointer[0], tarPointers);



//for (int i = 0; i < tarPointers.size(); i++)
//{
//	Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
//	drawContours(srcImg, tarPointers, i, color, 1, 8, vector<Vec4i>(), 0, Point());
//}

//for (int i = 0; i < templatePointer.size(); i++)
//{
//	Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
//	drawContours(srcImg, templatePointer, i, color, 1, 8, vector<Vec4i>(), 0, Point());
//}

for (int i = 0; i < resPointer.size(); i++)
{
	Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
	drawContours(srcImg, resPointer, i, color, 1, 8, vector<Vec4i>(), 0, Point());
}

//Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
//drawContours(srcImg, tarPointer, 0, color, 1, 8, vector<Vec4i>(), 0, Point());
//srcImg.release();

//提取指针目标
//Mat pointerImg = rgbHSVrgb(srcImg);//将3通道图像转化为二值图像
//

//int nCir = circles.size();
//tmpNeedle = findTargetContour(circles[0], contours);//找到指针边界
//needle.push_back(tmpNeedle);
//pointerImg.release();//指针图像释放
/*
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(srcImg, needle, 0, color, 1, 8, vector<Vec4i>(), 0, Point());
float val2Pts = twoPtsVal(circles[0], needle[0], start_deg, end_deg);
cout << val2Pts << endl;
float valFitLine = fitLineValue(needle[0], start_deg, end_deg);
cout << valFitLine << endl;
*/

//imshow("指针图像", pointerImg);
imshow("原始图像", srcImg);
cv::waitKey(0);
//system("pause");
return 0;

}

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值