OpenCV——自動光學檢查、對象分割和檢測

文章目錄

效果

在這裏插入圖片描述

代碼

#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
//#include <memory>
using namespace std;

// OpenCV includes
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

// OpenCV command line parser functions
// Keys accecpted by command line parser
const char *keys =
	{
		"{help h usage ? || print this message}"

		"{@image1 | /opencv4_vscode/opencv4例程/Chapter_05/data/test.pgm| Image1 to process}"
		"{@image2 | /opencv4_vscode/opencv4例程/Chapter_05/data/light.pgm| Image2 to process}"
		"{@segMethod |1| method=0使用除法,method=1使用減法}"
		"{@conMethod |1| method=0使用connectComponents();method=1使用connectComponentsWithStats();method=2 僅僅畫出輪廓}"};

//獲取光模式或相似背景
Mat calculateLightPattern(Mat img)
{
	Mat result;
	blur(img, result, Size(img.cols / 3, img.rows / 3));
	return result;
}

//獲取一個沒有光/背景的新圖像,method=0使用除法,method=1使用減法
Mat RemoveLight(Mat img, Mat background, int method)
{
	Mat result;
	//background.copyTo(result);
	if (method == 0)
	{
		Mat img32, background32;
		img.convertTo(img32, CV_32F);
		background.convertTo(background32, CV_32F);
		result = 1 - (img32 / background32);
		result.convertTo(result, CV_8U, 255);
	}
	if (method == 1)
	{
		result = background - img;
	}
	return result;
}

//獲取二值化後的圖像,方便分割。當使用除法獲取無背景圖像時,method=0,否則,method =1;
Mat twoValue(Mat image, int method)
{
	Mat result;
	int Threshold = 10, type = THRESH_BINARY;
	if (method == 0)
	{
		Threshold = 10, type = THRESH_BINARY;
	}
	else
	{
		Threshold = 20, type = THRESH_BINARY;
	}
	threshold(image, result, Threshold, 255, type);
	return result;
}

//獲取分割後的圖像。method=0使用connectComponents();method=1使用connectComponentsWithStats();method=2 僅僅畫出輪廓
void imageSegmentation(Mat img, int method)
{
	Mat labels, stats, centroids;
	RNG rng(12345);

	//creat output image coloring the objects and show area
	Mat output = Mat::zeros(img.rows, img.cols, CV_8UC3);

	//use connected components to divide our image in multiple connected component objects
	if (method == 0)
	{
		auto num_objects = connectedComponents(img, labels);
		if (num_objects < 2)
		{
			cout << "no objects detected" << endl;
			return;
		}
		else
		{
			cout << "Number of objects detected: " << num_objects - 1 << endl;
		}

		for (auto i = 1; i < num_objects; i++)
		{
			Mat mask = labels == i;
			output.setTo(Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), mask);
		}
	}

	//use connected components with stats to divide our image in multiple connected component objects
	if (method == 1)
	{
		auto num_objects = connectedComponentsWithStats(img, labels, stats, centroids);

		if (num_objects < 2)
		{
			cout << "no objects detected" << endl;
			return;
		}
		else
		{
			cout << "Number of objects detected: " << num_objects - 1 << endl;
		}

		for (auto i = 1; i < num_objects; i++)
		{
			cout << "Object" << i << "with pos: " << centroids.at<Point2d>(i) << "with area " << stats.at<int>(i, CC_STAT_AREA) << endl;
			Mat mask = labels == i;
			output.setTo(Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), mask);

			//draw text with area
			stringstream ss;
			ss << "area: " << stats.at<int>(i, CC_STAT_AREA);

			putText(output, ss.str(), centroids.at<Point2d>(i), FONT_HERSHEY_SIMPLEX, 0.4, Scalar(255, 255, 255));
		}
	}

	//use findContours to draw contours
	if (method == 2)
	{
		vector<vector<Point>> contours;
		findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
		//check the number of objects detected
		if (contours.size() == 0)
		{
			cout << "No objects detected" << endl;
			return;
		}
		else
		{
			cout << "Number of objects detected: " << contours.size() << endl;
		}

		//draw contours
		for (auto i = 0; i < contours.size(); i++)
		{
			drawContours(output, contours, i, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 1, LINE_8, Mat());
			//imshow("output", output);
		}
	}

	imshow("output", output);
}

int main(int argc, const char **argv)
{
	CommandLineParser parser(argc, argv, keys);
	parser.about("Chapter 4. PhotoTool v1.0.0");
	//If requires help show
	if (parser.has("help"))
	{
		parser.printMessage();
		return 0;
	}

	String imgFile1 = parser.get<String>(0);
	String imgFile2 = parser.get<string>(1);
	int sMethod = parser.get<int>(2);
	int cMethod = parser.get<int>(3);
	// Check if params are correctly parsed in his variables
	if (!parser.check())
	{
		parser.printErrors();
		return 0;
	}

	Mat test = imread(imgFile1);	   //輸入測試圖片
	Mat background = imread(imgFile2); //輸入背景圖片

	Mat blured;
	medianBlur(test, blured, 3); //消除噪點

	Mat Removed_Light = RemoveLight(blured, background, sMethod); //移除背景
	cvtColor(Removed_Light, Removed_Light, COLOR_BGR2GRAY);
	medianBlur(Removed_Light, Removed_Light, 3);
	Mat binary_img = twoValue(Removed_Light, sMethod); //二值化
	imshow("binary_img ", binary_img);

	imageSegmentation(binary_img, cMethod);

	waitKey(0);
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章