9、opencv图像分割多线程执行

opencv图像分割多线程执行

  • 1、模板多线程函数
  • 2、vector数组多线程函数
  • 3、多线程类

1、模板多线程函数

//实现标准库头文件中accumulate函数的并行版本
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;



using std::thread;
using std::vector;
using std::accumulate;
using std::cout;
using std::endl;

// 被执行的函数
template <typename Iterator, typename T> class Accum
{
public:
	void operator() (Iterator first, Iterator last, T& sum)
	{
		sum = 0;

		for (; first != last; ++first)
		{
			// 简单的计算素数
			auto k = std::sqrtf(*first);
			int i = 0;
			for (i = 2; i <= k; i++)
			{
				if ((*first) % i == 0)
				{
					break;
				}
			}

			if (i > k)
			{
				++sum;
			}
		}
	}
};








// 分发任务的函数
template <typename Iterator, typename T>
T ParallelAccum(Iterator first, Iterator last, T& sum)
{
	//计算迭代器中包含的元素数量
	const unsigned int len = std::distance(first, last);
	//若迭代器中没有元素则直接返回
	if (!len)
	{
		return sum;
	}

	//获取机器支持的并发线程数
	const unsigned int num_thread = thread::hardware_concurrency();

	cout << "总线程数:" << num_thread << endl;

	//最终实际上每个线程处理的元素个数
	const unsigned int block_size = len / num_thread;
	//保存每个线程累加的结果
	vector<T> results(num_thread);
	//启动比num_thread - 1个线程,因为main函数本身已开启一个线程
	vector<thread> threads(num_thread - 1);

	//开始并行计算
	Iterator block_begin = first;
	for (unsigned int i = 0; i < (num_thread - 1); ++i)
	{
		Iterator block_end = block_begin;
		//将迭代器向前推进一个块,到达当前块的末尾位置
		std::advance(block_end, block_size);
		//传递参数,通常情况下thread的构造函数将复制所提供的参数,需要将模板参数转为引用
		threads[i] = thread(Accum<Iterator, T>(), block_begin, block_end, std::ref(results[i]));
		block_begin = block_end;
	}
	//处理最后一个线程,由于block_size = len / num_thread得到的结果不一定为整数,该线程处理剩余的所有元素
	Accum<Iterator, T>()(block_begin, last, results[num_thread - 1]);
	//对threads中所有线程调用join()
	std::for_each(threads.begin(), threads.end(), std::mem_fn(&thread::join));
	//
	return accumulate(results.begin(), results.end(), sum);
}

// 计时结构
LARGE_INTEGER t1, t2, tc;

void time_begin()
{
	QueryPerformanceFrequency(&tc);
	QueryPerformanceCounter(&t1);
}

float time_end()
{
	QueryPerformanceCounter(&t2);
	return ((t2.QuadPart - t1.QuadPart) * 1.0 / tc.QuadPart) * 1000;
}


//图像分块
vector<Mat> splitImg(Mat image, int row, int col)
{
	int width = image.cols;
	int height = image.rows;
	int sub_width = width / col;
	int sub_height = height / row;
	vector<Mat> ceil_img;
	Mat image_cut, roi_img;
	for (int j = 0; j < row; j++)
	{
		for (int i = 0; i < col; i++)
		{
			Rect rect(i * sub_width, j * sub_height, sub_width, sub_height);
			image_cut = Mat(image, rect);
			roi_img = image_cut.clone();
			ceil_img.push_back(roi_img);
		}
	}

	return ceil_img;

}

//图像合并
Mat MergeImg(Mat image, vector<Mat> ceil_img, int row, int col)
{
	int width = image.cols;
	int height = image.rows;

	int sub_width = width / col;
	int sub_height = height / row;

	int t = 0;
	Mat MergeImage(image.size(), image.type());
	for (int j = 0; j < row; j++)
	{
		for (int i = 0; i < col; i++)
		{
			Rect ROI(i * sub_width, j * sub_height, sub_width, sub_height);
			ceil_img[t].copyTo(MergeImage(ROI));
			t++;
		}
	}

	return MergeImage;

}



// 被执行的函数
template <typename Iterator, typename T> class Accume
{
public:
	void operator() (Iterator first, Iterator last, T& sum)
	{
		sum = 1;
		for (; first != last; ++first)
		{
			//auto k = std::sqrtf(*first);
			auto ceil_img = *first;
			Rect rect = Rect(0, 0, ceil_img.cols, ceil_img.rows);
			//参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
			Scalar color = Scalar(0, 255, 0);
			rectangle(ceil_img, rect, color, 0.1, LINE_8);   //2表示线的宽度
			//可添加处理程序
			//imshow("处理图像", ceil_img);

		}

	}
};





// 分发任务的函数
template <typename Iterator, typename T>
T ParallelAccume(Iterator first, Iterator last, T& sum)
{
	//计算迭代器中包含的元素数量
	const unsigned int len = std::distance(first, last);
	//若迭代器中没有元素则直接返回
	if (!len)
	{
		return sum;
	}

	//获取机器支持的并发线程数
	const unsigned int num_thread = thread::hardware_concurrency();

	cout << "总线程数:" << num_thread << endl;

	//最终实际上每个线程处理的元素个数
	const unsigned int block_size = len / num_thread;
	//保存每个线程累加的结果
	vector<T> results(num_thread);
	//启动比num_thread - 1个线程,因为main函数本身已开启一个线程
	vector<thread> threads(num_thread - 1);

	//开始并行计算
	Iterator block_begin = first;
	for (unsigned int i = 0; i < (num_thread - 1); ++i)
	{
		Iterator block_end = block_begin;
		//将迭代器向前推进一个块,到达当前块的末尾位置
		std::advance(block_end, block_size);
		//传递参数,通常情况下thread的构造函数将复制所提供的参数,需要将模板参数转为引用
		threads[i] = thread(Accume<Iterator, T>(), block_begin, block_end, std::ref(results[i]));
		block_begin = block_end;
	}
	//处理最后一个线程,由于block_size = len / num_thread得到的结果不一定为整数,该线程处理剩余的所有元素
	Accume<Iterator, T>()(block_begin, last, results[num_thread - 1]);
	//对threads中所有线程调用join()
	std::for_each(threads.begin(), threads.end(), std::mem_fn(&thread::join));
	//
	return accumulate(results.begin(), results.end(), sum);
}



//********************************************************************************************************

// 被执行的函数
template <typename VecoterSrc, typename VecoterTemp, typename First, typename Fast, typename T> class Accume2
{
public:
	void operator() (VecoterSrc Srcv, VecoterSrc Tempv, First first, First last, T& sum)
	{
		cout << "处理个数: " << last - first << " 两个值:" << first << "&" << last << endl;
		cout << "" << endl;
		for (; first != last; ++first)
		{
			sum = 1;
			//auto k = std::sqrtf(*first);
			//auto ceil_img = *first;

			//auto ceil_img = Srcv[first];

			//Rect rect = Rect(0, 0, ceil_img.cols, ceil_img.rows);
			参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
			//Scalar color = Scalar(0, 255, 0);
			//rectangle(ceil_img, rect, color, 0.1, LINE_8);   //2表示线的宽度
			//可添加处理程序
			//imshow("处理图像", ceil_img);


			/*auto ceil_img = Srcv[first];*/

			//原图src处理
			Rect rect = Rect(0, 0, Srcv[first].cols, Srcv[first].rows);
			//参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
			Scalar color = Scalar(0, 255, 0);
			rectangle(Srcv[first], rect, color, 0.1, LINE_8);   //2表示线的宽度
			circle(Srcv[first], Point(Srcv[first].cols / 2, Srcv[first].rows / 2), 10, Scalar(0, 255, 0), -1);

			//模板图temp处理
			Rect rect2 = Rect(0, 0, Tempv[first].cols, Tempv[first].rows);
			//参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
			Scalar color2 = Scalar(255, 0, 0);
			rectangle(Tempv[first], rect, color2, 0.1, LINE_8);   //2表示线的宽度
			circle(Tempv[first], Point(Tempv[first].cols / 2, Tempv[first].rows / 2), 10, Scalar(0, 255, 0), -1);
		}

	}
};



// 分发任务的函数
template <typename VoctorImg, typename T>
T ParallelAccumed(VoctorImg Srcv, VoctorImg Tempv, T first, T last, T& sum)
{
	//计算迭代器中包含的元素数量
	//const unsigned int len = std::distance(first, last);
	const unsigned int len = last - first;
	//若迭代器中没有元素则直接返回
	if (!len)
	{
		return sum;
	}

	//获取机器支持的并发线程数
	const unsigned int num_thread = thread::hardware_concurrency();

	cout << "总线程数:" << num_thread << endl;

	//最终实际上每个线程处理的元素个数
	const unsigned int block_size = len / (num_thread - 1);
	//保存每个线程累加的结果
	vector<T> results(num_thread);
	//启动比num_thread - 1个线程,因为main函数本身已开启一个线程
	vector<thread> threads(num_thread - 1);

	//开始并行计算
	unsigned int block_begin = first;
	for (unsigned int i = 0; i < (num_thread - 1); ++i)
	{
		unsigned int block_end = block_begin + block_size;
		//将迭代器向前推进一个块,到达当前块的末尾位置
		//std::advance(block_end, block_size);
		//传递参数,通常情况下thread的构造函数将复制所提供的参数,需要将模板参数转为引用
		//threads[i] = thread(Accume(), block_begin, block_end, std::ref(results[i]));
		threads[i] = thread(Accume2<VoctorImg, VoctorImg, T, T, T>(), Srcv, Tempv, block_begin, block_end, std::ref(results[i]));
		block_begin = block_end;
	}
	//处理最后一个线程,由于block_size = len / num_thread得到的结果不一定为整数,该线程处理剩余的所有元素
	//Accume()(block_begin, last, results[num_thread - 1]);

	Accume2<VoctorImg, VoctorImg, T, T, T>()(Srcv, Tempv, block_begin, last, results[num_thread - 1]);
	//对threads中所有线程调用join()
	std::for_each(threads.begin(), threads.end(), std::mem_fn(&thread::join));
	//
	return accumulate(results.begin(), results.end(), sum);
}





int main()
{
	int sum = 0;

	Mat src;
	src = imread("../Image.bmp");
	if (!src.data) { printf("erro"); return false; }
	vector<Mat> ceil_img = splitImg(src, 7, 10);

	Mat templ;
	templ = imread("../banjing.jpeg");
	if (!templ.data) { printf("erro"); return false; }
	vector<Mat> ceil_img2 = splitImg(templ, 7, 10);

	//****************************************  Accume2  **********************************************

		// 并行计算示例
	time_begin();
	sum = ParallelAccumed<vector<Mat>, int>(ceil_img, ceil_img2, 0, ceil_img.size(), sum);
	cout << "time thread: " << time_end() << ", sum = " << sum << endl;


	// 一般计算示例
		/*time_begin();
		Accume2, vector,int,int,int> a;
		a(ceil_img, ceil_img2,0, ceil_img.size(),sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;*/

	Mat MergeImage = MergeImg(src, ceil_img, 7, 10);
	namedWindow("merge", WINDOW_NORMAL);
	imshow("merge", MergeImage);

	Mat MergeImage2 = MergeImg(templ, ceil_img2, 7, 10);
	namedWindow("merge2", WINDOW_NORMAL);
	imshow("merge2", MergeImage2);

	waitKey(0);




	//***************************************  Accume1  *****************************************************

	/*

		// 并行计算示例
		time_begin();
		sum = ParallelAccume(ceil_img.cbegin(), ceil_img.cend(), sum);
		cout << "time thread: " << time_end() << ", sum = " << sum << endl;


		// 一般计算示例
		time_begin();
		Accume::iterator, int> a;
		a(ceil_img.begin(), ceil_img.end(), sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;

		Mat MergeImage = MergeImg(src, ceil_img, 10, 10);

		namedWindow("merge", WINDOW_NORMAL);
		imshow("merge", MergeImage);

		waitKey(0);

	*/

	//********************************** Accum0 *********************************************************


	/*

		// 装备任务队列
		vector i_vec;
		int sum = 0;
		for (int i = 1; i != 501000; ++i)  //多数才有优势
		{
			i_vec.push_back(i);
		}

		// 并行计算示例
		time_begin();
		sum = ParallelAccum(i_vec.cbegin(), i_vec.cend(), sum);
		cout << "time thread: " << time_end() << ", sum = " << sum << endl;

		// 一般计算示例
		time_begin();
		Accum::iterator, int> a;
		a(i_vec.begin(), i_vec.end(), sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;

	*/
	return 0;
}

2、vector数组多线程函数

//实现标准库头文件中accumulate函数的并行版本
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;



//using std::thread;
//using std::vector;
//using std::accumulate;
//using std::cout;
//using std::endl;



// 计时结构 
LARGE_INTEGER t1, t2, tc;

void time_begin()
{
	QueryPerformanceFrequency(&tc);
	QueryPerformanceCounter(&t1);
}

float time_end()
{
	QueryPerformanceCounter(&t2);
	return ((t2.QuadPart - t1.QuadPart) * 1.0 / tc.QuadPart) * 1000;
}


//图像分块
vector<Mat> splitImg(Mat image, int row, int col)
{
	int width = image.cols;
	int height = image.rows;
	int sub_width = width / col;
	int sub_height = height / row;
	vector<Mat> ceil_img;
	Mat image_cut, roi_img;
	for (int j = 0; j < row; j++)
	{
		for (int i = 0; i < col; i++)
		{
			Rect rect(i * sub_width, j * sub_height, sub_width, sub_height);
			image_cut = Mat(image, rect);
			roi_img = image_cut.clone();
			ceil_img.push_back(roi_img);
		}
	}

	return ceil_img;

}

//图像合并
Mat MergeImg(Mat image, vector<Mat> ceil_img, int row, int col)
{
	int width = image.cols;
	int height = image.rows;

	int sub_width = width / col;
	int sub_height = height / row;

	int t = 0;
	Mat MergeImage(image.size(), image.type());
	for (int j = 0; j < row; j++)
	{
		for (int i = 0; i < col; i++)
		{
			Rect ROI(i * sub_width, j * sub_height, sub_width, sub_height);
			ceil_img[t].copyTo(MergeImage(ROI));
			t++;
		}
	}

	return MergeImage;

}



//*************************************************************************************************************
//模面检测
int CheckFace(Mat srcImg, Mat tempImg, int& num, int first)
{
	Mat imgSrcRef = srcImg;
	Mat imgSrcTest = tempImg;

	//精确到毫秒
  /*  cout << "****************************** t3 ******************************" << endl;
	long ts = cv::getTickCount();*/

	// 并行计算示例
	//time_begin();

	 预处理参考图像,主要是二值化
	Mat imgGrayRef;

	cvtColor(imgSrcRef, imgGrayRef, COLOR_BGR2GRAY);


	 预处理参考图像,主要是二值化
	Mat imgGrayTest;

	cvtColor(imgSrcTest, imgGrayTest, COLOR_BGR2GRAY);


	// 两张图片做对比
	Mat diffimg = imgGrayRef - imgGrayTest;
	diffimg = 255 - diffimg;
	Mat diffimgEro;
	Mat diffimgDil;
	/*namedWindow("result", WINDOW_FREERATIO);
	imshow("result", diffimg);
	waitKey(0);*/


	GaussianBlur(diffimg, diffimg, Size(5, 5), 4.5);
	adaptiveThreshold(diffimg, diffimg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 5, 3);



	//threshold(diffimg, diffimg, 0, 255, THRESH_BINARY | THRESH_OTSU);
   /* namedWindow("result", WINDOW_FREERATIO);
	imshow("result", diffimg);
	waitKey(0);*/


	Mat element = getStructuringElement(MORPH_RECT, Size(2, 4));
	morphologyEx(diffimg, diffimgEro, MORPH_DILATE, element);
	element = getStructuringElement(MORPH_RECT, Size(4, 4));
	morphologyEx(diffimgEro, diffimgDil, MORPH_ERODE, element);

	 查看预处理后的效果
	//namedWindow("result", WINDOW_FREERATIO);
	//imshow("result", diffimgDil);
	//waitKey(0);



	long ts3 = cv::getTickCount();

	// 开始BLOB分析
	SimpleBlobDetector::Params params;
	//params.minDistBetweenBlobs=120;
	params.filterByArea = true;
	params.minArea = 30;
	params.maxArea = 2000;

	params.filterByCircularity = false;

	params.filterByColor = false;
	params.filterByConvexity = false;
	params.filterByInertia = false;

	Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
	vector<KeyPoint> keypoints;
	detector->detect(diffimgDil, keypoints);

	// 输出检测到的异物点的个数(对于较大的异物,对应的数量可能超过1个,但不影响是否存在异物的判断),可注释掉
	// 也可以通过keypoints[i].pt.x 和 keypoints[i].pt.x输出坐标值,过滤掉非ROI区域的点

	cout << keypoints.size() << endl;
	 通过图片查看BLOB分析结果。可注释掉
	//Mat im_with_keypoints;
	drawKeypoints(imgGrayTest, keypoints, tempImg, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

	//模板图temp处理
	Rect rect2 = Rect(0, 0, tempImg.cols, tempImg.rows);
	//参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
	Scalar color2 = Scalar(255, 0, 0);
	rectangle(tempImg, rect2, color2, 0.1, LINE_8);   //2表示线的宽度
	circle(tempImg, Point(tempImg.cols / 2, tempImg.rows / 2), 10, Scalar(0, 255, 0), -1);
	putText(tempImg, to_string(first), Point(tempImg.cols / 2, tempImg.rows / 2), FONT_HERSHEY_COMPLEX, 3, Scalar(250, 225, 100));


	//原图src处理
	Rect rect = Rect(0, 0, srcImg.cols, srcImg.rows);
	//参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
	Scalar color = Scalar(0, 255, 0);
	rectangle(srcImg, rect, color, 0.1, LINE_8);   //2表示线的宽度
	circle(srcImg, Point(srcImg.cols / 2, srcImg.rows / 2), 10, Scalar(0, 255, 0), -1);
	putText(srcImg, to_string(first), Point(srcImg.cols / 2, srcImg.rows / 2), FONT_HERSHEY_COMPLEX, 3, Scalar(250, 225, 100));
	/* namedWindow("result", WINDOW_FREERATIO);
	imshow("result", im_with_keypoints);
	waitKey(0);*/

	//Sleep(1000);

	long te3 = cv::getTickCount();
	cout << "Time3 毫秒: " << (te3 - ts3) / cv::getTickFrequency() * 1000 << " " << "ms" << std::endl;
	cout << "Time3 秒: " << (te3 - ts3) / cv::getTickFrequency() << " " << "s" << std::endl;

	num += keypoints.size();
	// 判断是否存在异物
	bool isNG = false;
	if (keypoints.size() > 0)
	{
		isNG = true;
	}
	cout << isNG << endl;

	//Sleep(1000);
	/*long te = cv::getTickCount();
	cout << "Time 毫秒: " << (te - ts) / cv::getTickFrequency() * 1000 << " " << "ms" << std::endl;
	cout << "Time 秒: " << (te - ts) / cv::getTickFrequency() << " " << "s" << std::endl;*/
	//cout << "time block: " << time_end() << ", sum = " << keypoints.size() << endl;
	return 1;
}


//********************************************************************************************************

 被执行的函数
//template  class Accume2
//{
//public:
//	void operator() (VecoterSrc Srcv, VecoterSrc Tempv, First first, First last, T& sum)
//	{
//		cout << "处理个数: " << last - first << " 两个值:" << first << "&" << last << endl;
//		cout << "" << endl;
//
//		sum = 0;
//		for (; first != last; ++first)
//		{
//			//sum = 1;
//
//			CheckFace(Srcv[first], Tempv[first], sum, first);
//
//		}
//
//	}
//};


// 被执行的函数
void Accume2(vector<Mat> Srcv, vector<Mat> Tempv, int first, int last, int& sum)
{

		cout << "处理个数: " << last - first << " 两个值:" << first << "&" << last << endl;
		cout << "" << endl;

		sum = 0;
		for (; first != last; ++first)
		{
			//sum = 1;

			CheckFace(Srcv[first], Tempv[first], sum, first);

		}

	
};


// 分发任务的函数

int ParallelAccumed(vector<Mat> Srcv, vector<Mat> Tempv, int first, int last, int& sum)
{
	//计算迭代器中包含的元素数量
	//const unsigned int len = std::distance(first, last);
	const unsigned int len = last - first;
	//若迭代器中没有元素则直接返回
	if (!len)
	{
		return sum;
	}

	//获取机器支持的并发线程数
	const unsigned int num_thread = thread::hardware_concurrency();

	cout << "总线程数:" << num_thread << endl;

	//最终实际上每个线程处理的元素个数
	const unsigned int block_size = len / (num_thread - 1);
	//保存每个线程累加的结果
	vector<int> results(num_thread);
	//启动比num_thread - 1个线程,因为main函数本身已开启一个线程
	vector<thread> threads(num_thread - 1);

	//开始并行计算
	unsigned int block_begin = first;
	for (unsigned int i = 0; i < (num_thread - 1); ++i)
	{
		unsigned int block_end = block_begin + block_size;
		//将迭代器向前推进一个块,到达当前块的末尾位置
		//std::advance(block_end, block_size);
		//传递参数,通常情况下thread的构造函数将复制所提供的参数,需要将模板参数转为引用
		//threads[i] = thread(Accume(), block_begin, block_end, std::ref(results[i]));
		threads[i] = thread(Accume2, Srcv, Tempv, block_begin, block_end, std::ref(results[i]));
		block_begin = block_end;
	}
	//处理最后一个线程,由于block_size = len / num_thread得到的结果不一定为整数,该线程处理剩余的所有元素
	//Accume()(block_begin, last, results[num_thread - 1]);

	Accume2(Srcv, Tempv, block_begin, last, results[num_thread - 1]);
	//对threads中所有线程调用join()
	std::for_each(threads.begin(), threads.end(), std::mem_fn(&thread::join));
	//
	return accumulate(results.begin(), results.end(), sum);
}



class MyThread {

public:
	
	void myThread_in(int a,int c)
	{
		cout << "thread start "<<a <<";;;" << c << endl;

	}

};




int main()
{

	MyThread  Thread;
	std::thread thread_test(&MyThread::myThread_in, &Thread,1000,9999);
	thread_test.join();


	int sum = 0;
	int Row = 5, Clo = 5;


	Mat src;
	src = imread("../pp/40/ok/Image_27.bmp");
	if (!src.data) { printf("erro"); return false; }
	vector<Mat> ceil_img = splitImg(src, Row, Clo);

	Mat templ;
	templ = imread("../pp/40/ng/Image_62.bmp");
	if (!templ.data) { printf("erro"); return false; }
	vector<Mat> ceil_img2 = splitImg(templ, Row, Clo);

	//****************************************  Accume2  **********************************************

	int num = 0;
	Mat tempg;
	templ.copyTo(tempg);
	CheckFace(src, tempg, num, 1);
	namedWindow("tempg", WINDOW_NORMAL);
	imshow("tempg", tempg);
	cout << "总数" << num << endl;


	// 并行计算示例
	time_begin();
	sum = ParallelAccumed(ceil_img, ceil_img2, 0, ceil_img.size(), sum);
	cout << "time thread all: " << time_end() << ", sum = " << sum << endl;


	// 一般计算示例
		/*time_begin();
		Accume2, vector,int,int,int> a;
		a(ceil_img, ceil_img2,0, ceil_img.size(),sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;*/

	Mat MergeImage = MergeImg(src, ceil_img, Row, Clo);
	namedWindow("mergeSrc", WINDOW_NORMAL);
	imshow("mergeSrc", MergeImage);

	Mat MergeImage2 = MergeImg(templ, ceil_img2, Row, Clo);
	namedWindow("merge2Temp", WINDOW_NORMAL);
	imshow("merge2Temp", MergeImage2);

	waitKey(0);




	//***************************************  Accume1  *****************************************************

	/*

		// 并行计算示例
		time_begin();
		sum = ParallelAccume(ceil_img.cbegin(), ceil_img.cend(), sum);
		cout << "time thread: " << time_end() << ", sum = " << sum << endl;


		// 一般计算示例
		time_begin();
		Accume::iterator, int> a;
		a(ceil_img.begin(), ceil_img.end(), sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;

		Mat MergeImage = MergeImg(src, ceil_img, 10, 10);

		namedWindow("merge", WINDOW_NORMAL);
		imshow("merge", MergeImage);

		waitKey(0);

	*/

	//********************************** Accum0 *********************************************************


	/*

		// 装备任务队列
		vector i_vec;
		int sum = 0;
		for (int i = 1; i != 501000; ++i)  //多数才有优势
		{
			i_vec.push_back(i);
		}

		// 并行计算示例
		time_begin();
		sum = ParallelAccum(i_vec.cbegin(), i_vec.cend(), sum);
		cout << "time thread: " << time_end() << ", sum = " << sum << endl;

		// 一般计算示例
		time_begin();
		Accum::iterator, int> a;
		a(i_vec.begin(), i_vec.end(), sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;

	*/
	return 0;
}

3、多线程类

//实现标准库头文件中accumulate函数的并行版本
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"

#include "Face.h"

using namespace std;
using namespace cv;



//using std::thread;
//using std::vector;
//using std::accumulate;
//using std::cout;
//using std::endl;



// 计时结构 
LARGE_INTEGER t1, t2, tc;

void time_begin()
{
	QueryPerformanceFrequency(&tc);
	QueryPerformanceCounter(&t1);
}

float time_end()
{
	QueryPerformanceCounter(&t2);
	return ((t2.QuadPart - t1.QuadPart) * 1.0 / tc.QuadPart) * 1000;
}


//图像分块
vector<Mat> splitImg(Mat image, int row, int col)
{
	int width = image.cols;
	int height = image.rows;
	int sub_width = width / col;
	int sub_height = height / row;
	vector<Mat> ceil_img;
	Mat image_cut, roi_img;
	for (int j = 0; j < row; j++)
	{
		for (int i = 0; i < col; i++)
		{
			Rect rect(i * sub_width, j * sub_height, sub_width, sub_height);
			image_cut = Mat(image, rect);
			roi_img = image_cut.clone();
			ceil_img.push_back(roi_img);
		}
	}

	return ceil_img;

}

//图像合并
Mat MergeImg(Mat image, vector<Mat> ceil_img, int row, int col)
{
	int width = image.cols;
	int height = image.rows;

	int sub_width = width / col;
	int sub_height = height / row;

	int t = 0;
	Mat MergeImage(image.size(), ceil_img[0].type());
	for (int j = 0; j < row; j++)
	{
		for (int i = 0; i < col; i++)
		{
			Rect ROI(i * sub_width, j * sub_height, sub_width, sub_height);
			ceil_img[t].copyTo(MergeImage(ROI));
			t++;
		}
	}

	return MergeImage;

}



class MyThread {

public:

	void myThread_in(int a, int c)
	{
		cout << "thread start " << a << ";;;" << c << endl;

	}

	//块检测
	void FaceCheckPart(Mat imgSrcRef, Mat imgSrcTest, int& num)
	{

		// 预处理模板图像,主要是二值化
		Mat imgGrayRef;
		cvtColor(imgSrcRef, imgGrayRef, COLOR_BGR2GRAY);
		//预处理参考图像,主要是二值化
		Mat imgGrayTest;
		cvtColor(imgSrcTest, imgGrayTest, COLOR_BGR2GRAY);
		// 两张图片做对比
		Mat diffimg = imgGrayRef - imgGrayTest;
		diffimg = 255 - diffimg;
		Mat diffimgEro;
		Mat diffimgDil;
		//高斯滤波
		GaussianBlur(diffimg, diffimg, Size(5, 5), 4.5);
		adaptiveThreshold(diffimg, diffimg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 5, 3);
		Mat element = getStructuringElement(MORPH_RECT, Size(2, 4));
		morphologyEx(diffimg, diffimgEro, MORPH_DILATE, element);
		element = getStructuringElement(MORPH_RECT, Size(4, 4));
		morphologyEx(diffimgEro, diffimgDil, MORPH_ERODE, element);

		// 开始BLOB分析
		SimpleBlobDetector::Params params;
		params.filterByArea = true;
		params.minArea = 30;
		params.maxArea = 2000;
		params.filterByCircularity = false;
		params.filterByColor = false;
		params.filterByConvexity = false;
		params.filterByInertia = false;
		Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
		vector<KeyPoint> keypoints;
		detector->detect(diffimgDil, keypoints);

		// 通过图片查看BLOB分析结果,可注释掉
		drawKeypoints(imgGrayTest, keypoints, imgSrcTest, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
		//num统计检测到的异物点的个数(对于较大的异物,对应的数量可能超过1个,但不影响是否存在异物的判断)
		num += keypoints.size();

	}
	//模面检测
	void CheckFace22(Mat srcImg, Mat tempImg, int& num, int first)
	{
		Mat imgSrcRef = srcImg;
		Mat imgSrcTest = tempImg;

		Mat imgGrayRef;

		cvtColor(imgSrcRef, imgGrayRef, COLOR_BGR2GRAY);


		 预处理参考图像,主要是二值化
		Mat imgGrayTest;

		cvtColor(imgSrcTest, imgGrayTest, COLOR_BGR2GRAY);


		// 两张图片做对比
		Mat diffimg = imgGrayRef - imgGrayTest;
		diffimg = 255 - diffimg;
		Mat diffimgEro;
		Mat diffimgDil;
		/*namedWindow("result", WINDOW_FREERATIO);
		imshow("result", diffimg);
		waitKey(0);*/


		GaussianBlur(diffimg, diffimg, Size(5, 5), 4.5);
		adaptiveThreshold(diffimg, diffimg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 5, 3);
		Mat element = getStructuringElement(MORPH_RECT, Size(2, 4));
		morphologyEx(diffimg, diffimgEro, MORPH_DILATE, element);
		element = getStructuringElement(MORPH_RECT, Size(4, 4));
		morphologyEx(diffimgEro, diffimgDil, MORPH_ERODE, element);

		 查看预处理后的效果
		//namedWindow("result", WINDOW_FREERATIO);
		//imshow("result", diffimgDil);
		//waitKey(0);



		
		// 开始BLOB分析
		SimpleBlobDetector::Params params;
		//params.minDistBetweenBlobs=120;
		params.filterByArea = true;
		params.minArea = 30;
		params.maxArea = 2000;

		params.filterByCircularity = false;

		params.filterByColor = false;
		params.filterByConvexity = false;
		params.filterByInertia = false;

		Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
		vector<KeyPoint> keypoints;
		detector->detect(diffimgDil, keypoints);

		// 输出检测到的异物点的个数(对于较大的异物,对应的数量可能超过1个,但不影响是否存在异物的判断),可注释掉
		// 也可以通过keypoints[i].pt.x 和 keypoints[i].pt.x输出坐标值,过滤掉非ROI区域的点

		//cout << keypoints.size() << endl;
		 通过图片查看BLOB分析结果。可注释掉
		//Mat im_with_keypoints;
		drawKeypoints(imgGrayTest, keypoints, tempImg, Scalar(0, 0, 255), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

		//模板图temp处理
		Rect rect2 = Rect(0, 0, tempImg.cols, tempImg.rows);
		//参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
		Scalar color2 = Scalar(255, 0, 0);
		rectangle(tempImg, rect2, color2, 0.1, LINE_8);   //2表示线的宽度
		circle(tempImg, Point(tempImg.cols / 2, tempImg.rows / 2), 10, Scalar(0, 255, 0), -1);
		putText(tempImg, to_string(first), Point(tempImg.cols / 2, tempImg.rows / 2), FONT_HERSHEY_COMPLEX, 3, Scalar(250, 225, 100));


		//原图src处理
		Rect rect = Rect(0, 0, srcImg.cols, srcImg.rows);
		//参数说明:1矩形左上角点的横坐标 2矩形左上角点的纵坐标 3矩形的长 4矩形的宽
		Scalar color = Scalar(0, 255, 0);
		rectangle(srcImg, rect, color, 0.1, LINE_8);   //2表示线的宽度
		circle(srcImg, Point(srcImg.cols / 2, srcImg.rows / 2), 10, Scalar(0, 255, 0), -1);
		putText(srcImg, to_string(first), Point(srcImg.cols / 2, srcImg.rows / 2), FONT_HERSHEY_COMPLEX, 3, Scalar(250, 225, 100));
		/* namedWindow("result", WINDOW_FREERATIO);
		imshow("result", im_with_keypoints);
		waitKey(0);*/

		//Sleep(1000);

		

		num += keypoints.size();
		// 判断是否存在异物
		bool isNG = false;
		if (keypoints.size() > 0)
		{
			isNG = true;
		}
		//cout << isNG << endl;

		
		//return 1;
	}

	// 被执行的函数
	void Accume22(vector<Mat> Srcv, vector<Mat> Tempv, int first, int last, int& sum)
	{

		/*	cout << "处理个数: " << last - first << " 两个值:" << first << "&" << last << endl;
			cout << "" << endl;*/

		sum = 0;
		for (; first != last; ++first)
		{
			//sum = 1;
			CheckFace22(Srcv[first], Tempv[first], sum,first);
			/*FaceCheckPart(Srcv[first], Tempv[first], sum);*/
			//FaceCheckPart(Srcv[first], Testv[first], sum);
		}


	}

	// 分发任务的函数

	int ParallelAccumed22(vector<Mat> Srcv, vector<Mat> Tempv, int first, int last, int& sum)
	{
		//MyThread  Thread;
		//计算迭代器中包含的元素数量
		//const unsigned int len = std::distance(first, last);
		const unsigned int len = last - first;
		//若迭代器中没有元素则直接返回
		if (!len)
		{
			return sum;
		}

		//获取机器支持的并发线程数
		const unsigned int num_thread = thread::hardware_concurrency();

		//cout << "总线程数:" << num_thread << endl;

		//最终实际上每个线程处理的元素个数
		const unsigned int block_size = len / (num_thread - 1);
		//保存每个线程累加的结果
		vector<int> results(num_thread);
		//启动比num_thread - 1个线程,因为main函数本身已开启一个线程
		vector<thread> threads(num_thread - 1);

		//开始并行计算
		unsigned int block_begin = first;
		for (unsigned int i = 0; i < (num_thread - 1); ++i)
		{
			unsigned int block_end = block_begin + block_size;
			//将迭代器向前推进一个块,到达当前块的末尾位置
			//std::advance(block_end, block_size);
			//传递参数,通常情况下thread的构造函数将复制所提供的参数,需要将模板参数转为引用
			//threads[i] = thread(Accume(), block_begin, block_end, std::ref(results[i]));
			threads[i] = thread(&MyThread::Accume22, this, Srcv, Tempv, block_begin, block_end, std::ref(results[i]));
			block_begin = block_end;
		}
		//处理最后一个线程,由于block_size = len / num_thread得到的结果不一定为整数,该线程处理剩余的所有元素
		//Accume()(block_begin, last, results[num_thread - 1]);

		MyThread::Accume22(Srcv, Tempv, block_begin, last, results[num_thread - 1]);
		//对threads中所有线程调用join()
		std::for_each(threads.begin(), threads.end(), std::mem_fn(&thread::join));
		//
		return accumulate(results.begin(), results.end(), sum);
	}



};




int main()
{

	MyThread  Thread;
	std::thread thread_test(&MyThread::myThread_in, &Thread, 1000, 9999);
	thread_test.join();


	int sum = 0;
	int Row = 5, Clo = 5;


	Mat src;
	src = imread("../pp/40/ok/Image_27.bmp");
	if (!src.data) { printf("erro"); return false; }
	vector<Mat> ceil_img = splitImg(src, Row, Clo);

	Mat templ;
	templ = imread("../pp/40/ng/Image_62.bmp");
	if (!templ.data) { printf("erro"); return false; }
	vector<Mat> ceil_img2 = splitImg(templ, Row, Clo);

	//****************************************  Accume2  **********************************************

	int num = 0;
	/*Mat tempg;
	templ.copyTo(tempg);
	CheckFace(src, tempg, num, 1);
	namedWindow("tempg", WINDOW_NORMAL);
	imshow("tempg", tempg);
	cout << "总数" << num << endl;*/

	
	IMFaceChk check;
	// 并行计算示例
	/*time_begin();
	 check.ParallelAccumed(ceil_img, ceil_img2, 0, ceil_img.size(), sum);
	cout << "线程时间: " << time_end() << ", sum = " << sum << endl;*/



	// 并行计算示例
	time_begin();
	sum = Thread.ParallelAccumed22(ceil_img, ceil_img2, 0, ceil_img.size(), sum);
	cout << "time thread all: " << time_end() << ", sum = " << sum << endl;


	// 一般计算示例
		/*time_begin();
		Accume2, vector,int,int,int> a;
		a(ceil_img, ceil_img2,0, ceil_img.size(),sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;*/

	Mat MergeImage = MergeImg(src, ceil_img, Row, Clo);
	namedWindow("mergeSrc", WINDOW_NORMAL);
	imshow("mergeSrc", MergeImage);

	Mat MergeImage2 = MergeImg(templ, ceil_img2, Row, Clo);
	namedWindow("merge2Temp", WINDOW_NORMAL);
	imshow("merge2Temp", MergeImage2);

	waitKey(0);




	//***************************************  Accume1  *****************************************************

	/*

		// 并行计算示例
		time_begin();
		sum = ParallelAccume(ceil_img.cbegin(), ceil_img.cend(), sum);
		cout << "time thread: " << time_end() << ", sum = " << sum << endl;


		// 一般计算示例
		time_begin();
		Accume::iterator, int> a;
		a(ceil_img.begin(), ceil_img.end(), sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;

		Mat MergeImage = MergeImg(src, ceil_img, 10, 10);

		namedWindow("merge", WINDOW_NORMAL);
		imshow("merge", MergeImage);

		waitKey(0);

	*/

	//********************************** Accum0 *********************************************************


	/*

		// 装备任务队列
		vector i_vec;
		int sum = 0;
		for (int i = 1; i != 501000; ++i)  //多数才有优势
		{
			i_vec.push_back(i);
		}

		// 并行计算示例
		time_begin();
		sum = ParallelAccum(i_vec.cbegin(), i_vec.cend(), sum);
		cout << "time thread: " << time_end() << ", sum = " << sum << endl;

		// 一般计算示例
		time_begin();
		Accum::iterator, int> a;
		a(i_vec.begin(), i_vec.end(), sum);
		cout << "time: " << time_end() << ", sum = " << sum << endl;

	*/
	return 0;
}

你可能感兴趣的:(机器视觉,opencv,人工智能,计算机视觉)