最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++?OpenCV實(shí)戰(zhàn)之零部件的自動光學(xué)檢測

 更新時間:2022年09月14日 11:24:56   作者:一個熱愛學(xué)習(xí)的深度渣渣  
這篇文章主要為大家介紹一個C++?OpenCV的實(shí)戰(zhàn)——零部件的自動光學(xué)檢測,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

一、背景

首先任務(wù)背景是AOI(自動光學(xué)檢測)

最重要的目的在于:將前景和物體進(jìn)行分割與分類;

場景示意圖:

需要注意,在螺母的傳送帶上,需要有前光和背光,給物體打光才能夠拍攝清晰的圖像;

二、基礎(chǔ)知識

首先分為以下幾步:

1、噪聲抑制(預(yù)處理)

2、背景移除(分割)

3、二值化

4、連通域、輪廓查找算法

降噪算法

先使用中值濾波對椒鹽噪聲進(jìn)行過濾,再使用高斯濾波對物體邊緣進(jìn)行模糊;

背景移除

首先有兩種方案可以實(shí)現(xiàn)背景移除,也就是減法和除法;

連通圖檢測計數(shù)

首先連通域類型分為4路連通和8路連通:

使用連通圖檢測算法,可以將不連通的每個物體都用不同顏色劃分出來;

三、代碼實(shí)現(xiàn)

1、實(shí)現(xiàn)多窗口展示

如果想要多張圖像展示在一個窗口中,也就是實(shí)現(xiàn)拼接圖片的操作,使用Python代碼實(shí)現(xiàn)起來可能比較便捷,C++代碼需要定義一個類,并且實(shí)際編寫也比較繁瑣;

class Display {
private:
	int cols, rows, width, height;
	String title;
	vector<String> win_names;
	vector<Mat> images;
	Mat canvas;
public:
	Display(String t, int c, int r, int flags) :title(t), cols(c), rows(r) {
		height = 1080;
		width = 1920;
		namedWindow(title, flags);
		canvas = Mat(height, width, CV_8UC3);
		imshow(title, canvas);
	}

	int add_window(String win_name, Mat image, bool flag = true) {
		win_names.push_back(win_name);
		images.push_back(image);
		if (flag) {
			draw();
		}
		return win_names.size();
	}
	
    // 實(shí)現(xiàn)刪除窗口
	int delete_window(String win_name) {
		int index = 0;
		for (const auto& it : win_names) {
			if (it == win_name) break;
			index++;
		}
		win_names.erase(win_names.begin() + index);
		images.erase(images.begin() + index);

		return win_names.size();
	}

	void draw() {
		canvas.setTo(Scalar(20, 20, 20));
		int single_width = width / cols;
		int single_height = height / rows;
		int max_win = win_names.size() > cols * rows ? cols * rows : win_names.size();
		
		int i = 0;
		auto iw = win_names.begin();
		for (auto it = images.begin(); it != images.end()&&i<max_win; it++,i++,iw++) {
			String win_name = *iw;
			Mat img = *it;

			int x = (single_width) * (i % cols);
			int y = (single_height)*floor(i * 1.0 / cols);
			Rect mask(x, y, single_width, single_height);

			rectangle(canvas, mask, Scalar(255, 255, 255), 9);

			Mat resized_img;
			resize(img, resized_img, Size(single_width, single_height));

			Mat sub_canvas(canvas, mask);
			if (resized_img.channels() == 1) {
				cvtColor(resized_img, resized_img, COLOR_GRAY2BGR);
			}
			resized_img.copyTo(sub_canvas);
            putText(sub_canvas, win_name, Point(50, 50), FONT_HERSHEY_COMPLEX, 2, Scalar(0, 0, 255), 3, LINE_AA);
		}
		imshow(title, canvas);
	}
};

// 使用智能指針
shared_ptr<Display> multi_window;

int main(int argc, char** argv)
{

	// 實(shí)現(xiàn)多窗口
	String total_path = "imgpath";
	String background_path = "imgpath";

	Mat abc = imread(total_path, 0);

	multi_window = make_shared<Display>("Review for all", 3, 2, WINDOW_NORMAL);
	multi_window->add_window("ABC", abc);
	multi_window->add_window("ABCC", abc);
    multi_window->delete_window("ABC");		// 也支持刪除窗口
	multi_window->draw();

	waitKey(0);
	return 0;
}

2、降噪處理

采用中值濾波+高斯濾波結(jié)合的降噪方法:

Mat get_background(const Mat& bg){
    Mat img;
    medianBlur(bg,img,3);
    GaussianBlur(bg,img,Size(3,3),0);
    return img;
}

Mat smoothen_img(const Mat& noise_img){
    Mat img;
    medianBlur(noise_img,img,5);
    GaussianBlur(img,img,Size(3,3),0);
    return img;
}

3、背景去除

分為兩種方式,一種為減法,一種為除法;

Mat remove_background_divide(Mat image, Mat background) {
	Mat tmp;
	Mat fg, bg;
	image.convertTo(fg, CV_32F);
	background.convertTo(bg, CV_32F);
	tmp = 1 - (fg / bg);
	tmp.convertTo(tmp, CV_8U, 255);
	return tmp;
}

Mat remove_background_minus(Mat image, Mat background) {
	return background - image;
}

從結(jié)果圖上看,使用除法的方式能更好的保留白色部分的信息,因此選用除法的方式;

4、連通圖實(shí)現(xiàn)

對二值化后的圖像進(jìn)行連通域劃分,并且用隨機(jī)顏色繪制到Mask圖上;

void connection_check(Mat image) {
	Mat labels;
	int num = connectedComponents(image, labels);
	if (num <= 1) {
		cout << "No stuff detect!!" << endl;
		return;
	}
	else
	{
		cout << num << " objects detected!!" << endl;
	}

	Mat display = Mat::zeros(image.rows, image.cols, CV_8UC3);
	for (int i = 1; i < num; i++) {
		Mat mask = (labels == i);
		display.setTo(random_color_generator(seed), mask);
	}
	multi_window->add_window("Segment", display);
}

5、計算連通域面積

OpenCV中也自帶了對面積區(qū)域的計算:

void connection_heavy_check(Mat image) {
    Mat labels, stats, centroids;
    int num =connectedComponentsWithStats(image, labels, stats, centroids);
    if (num <= 1) {
        cout << "No stuff detect!!" << endl;
        return;
    }
    else
    {
        cout << num << " objects detected!!" << endl;
    }
    Mat display = Mat::zeros(image.rows, image.cols, CV_8UC3);
    for (int i = 1; i < num; i++) {
        // 得到連通域的質(zhì)心點(diǎn)
        Point2i pt(centroids.at<double>(i, 0), centroids.at<double>(i, 1));
        // 打印標(biāo)簽和連通域坐標(biāo)和面積
        cout << "Stuff #" << i << ", Position: " << pt << " ,Area: " << stats.at<int>(i, CC_STAT_AREA) << endl;
        Mat mask = (labels == i);
        display.setTo(random_color_generator(seed), mask);
        stringstream ss;
        ss << stats.at<int>(i, CC_STAT_AREA);
        putText(display, ss.str(), pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255), 2);
    }
    multi_window->add_window("Segment more", display);
}

6、輪廓檢測

實(shí)現(xiàn)對物體輪廓的檢測;

void get_contour(Mat image) {
    vector<vector<Point>> contours;
    findContours(image, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    Mat display = Mat::zeros(image.rows, image.cols, CV_8UC3);
    if (contours.size() == 0) {
        cout << "No contour detect!!" << endl;
        return;
    }
    else
    {
        cout << contours.size() << " contour detected!!" << endl;
    }
    for (int i = 0; i < contours.size(); i++) {
        drawContours(display, contours, i, random_color_generator(seed), 2);
    }
    multi_window->add_window("CONTOURS", display);
}

從上結(jié)果圖可知,檢測到的輪廓并不包含內(nèi)部輪廓,如果想檢測所有輪廓應(yīng)該將findContours函數(shù)中的類型參數(shù)改為RETR_LIST即可;

四、總結(jié)

本次項目中涉及的技術(shù)點(diǎn)如下:

  • 多窗口展示
  • 背景去除
  • 連通圖的實(shí)現(xiàn)
  • 輪廓邊緣檢測

并且在實(shí)際的C++代碼中,還涉及了智能指針等高階知識;

工業(yè)質(zhì)檢項目作為視覺領(lǐng)域較為成熟的落地項目,其大部分都是基于深度學(xué)習(xí)的方式實(shí)現(xiàn)了,但如果能掌握一些OpenCV的方法,也可以在項目中起到優(yōu)化效果的作用;

到此這篇關(guān)于C++ OpenCV實(shí)戰(zhàn)之零部件的自動光學(xué)檢測的文章就介紹到這了,更多相關(guān)C++ OpenCV光學(xué)檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++運(yùn)算符重載的方法詳細(xì)解析

    C++運(yùn)算符重載的方法詳細(xì)解析

    運(yùn)算符重載的方法是定義一個重載運(yùn)算符的函數(shù),在需要執(zhí)行被重載的運(yùn)算符時,系統(tǒng)就自動調(diào)用該函數(shù),以實(shí)現(xiàn)相應(yīng)的運(yùn)算。也就是說,運(yùn)算符重載是通過定義函數(shù)實(shí)現(xiàn)的
    2013-10-10
  • 基于Qt實(shí)現(xiàn)C/C++調(diào)用Matlab函數(shù)全過程

    基于Qt實(shí)現(xiàn)C/C++調(diào)用Matlab函數(shù)全過程

    這篇文章給大家詳細(xì)介紹了基于Qt平臺實(shí)現(xiàn)C/C++調(diào)用Matlab函數(shù)全流程,文中通過圖文和代碼示例給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • C++ Eigen庫計算矩陣特征值及特征向量

    C++ Eigen庫計算矩陣特征值及特征向量

    這篇文章主要為大家詳細(xì)介紹了C++ Eigen庫計算矩陣特征值及特征向量,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • C語言運(yùn)算符深入探究優(yōu)先級與結(jié)合性及種類

    C語言運(yùn)算符深入探究優(yōu)先級與結(jié)合性及種類

    C語言運(yùn)算符號指的是運(yùn)算符號。C語言中的符號分為10類:算術(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位操作運(yùn)算符、賦值運(yùn)算符、條件運(yùn)算符、逗號運(yùn)算符、指針運(yùn)算符、求字節(jié)數(shù)運(yùn)算符和特殊運(yùn)算符
    2022-05-05
  • C語言實(shí)現(xiàn)餐飲管理與點(diǎn)餐系統(tǒng)

    C語言實(shí)現(xiàn)餐飲管理與點(diǎn)餐系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)餐飲管理與點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • 利用Matlab繪制好看的弦圖

    利用Matlab繪制好看的弦圖

    弦圖在python中以及R中非常常見,但是MATLAB中卻始終沒有相關(guān)函數(shù)。本文就來用Matlab繪制一些好看的弦圖,感興趣的小伙伴可以了解一下
    2022-08-08
  • C語言中你不知道的隱式類型轉(zhuǎn)換規(guī)則詳解

    C語言中你不知道的隱式類型轉(zhuǎn)換規(guī)則詳解

    在C語言中,類型轉(zhuǎn)換的方式一般可分為隱式類型轉(zhuǎn)換和顯示類型轉(zhuǎn)換(也稱為強(qiáng)制類型轉(zhuǎn)換),其中隱式類型轉(zhuǎn)換由編譯器自動進(jìn)行,不需要程序員干預(yù),本文給大家詳細(xì)介紹了C語言中隱式類型轉(zhuǎn)換規(guī)則,需要的朋友可以參考下
    2024-01-01
  • 深入C++可見性與生命期的區(qū)別詳解

    深入C++可見性與生命期的區(qū)別詳解

    本篇文章對C++中可見性與生命期的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++中套接字庫sockpp的使用詳解

    C++中套接字庫sockpp的使用詳解

    sockpp是一個開源、簡單、現(xiàn)代的C++套接字庫,這篇文章主要為大家詳細(xì)介紹一下套接字庫sockpp的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下
    2023-11-11
  • 一文搞懂C語言中的文件操作

    一文搞懂C語言中的文件操作

    文件操作想必大家掌握的并不熟練,確實(shí)因為我們用的并不多,而本節(jié)內(nèi)容能夠讓大家初步認(rèn)識文件操作,從文件認(rèn)識到文件使用,讓我們對c語言文件操作有個初步的了解
    2022-11-11

最新評論

嘉禾县| 兰州市| 淅川县| 临颍县| 明星| 得荣县| 锡林郭勒盟| 普定县| 洱源县| 名山县| 旬邑县| 册亨县| 衡阳市| 万源市| 宁安市| 玉环县| 伊川县| 佛山市| 平安县| 郴州市| 新营市| 怀来县| 重庆市| 商城县| 汤原县| 郎溪县| 忻州市| 安岳县| 松滋市| 太和县| 宁安市| 开远市| 吉木乃县| 罗山县| 聂荣县| 盘锦市| 四川省| 成安县| 汕尾市| 彩票| 武冈市|