Qt 搭配 OpenCv 尋找亮點,圈出物件
Step 1.
使用燈泡的照片尋找亮點,放到電腦指定的位置
位置 : C:\\light.jpg |
Step 2.
判斷圖片是否存在
Mat src = imread("C:\\light.jpg");
if (src.empty())
{
std::cout << "Could not load image file!";
system("pause");
return 0;
} else {
// 準備圈出物件
}
全域參數,後面會使用
Mat src, threshold_output;
Mat src_gray;
RNG rng(12345);
int erosion_elem = 0;
int erosion_size = 5;
int dilation_elem = 0;
int dilation_size = 10;
include
#include "mainwindow.h"
#include <QApplication>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <QDebug>
using namespace cv;
using namespace std;
Step 3.
轉成灰度圖及平滑化
Mat src_result = src.clone();
// 轉成灰度圖
cvtColor(src, src_gray, CV_BGR2GRAY);
// 平滑化
blur(src_gray, src_gray, Size(3,3));
// 均衡化直方圖(應加對比效果)
equalizeHist( src_gray, src_gray);
// 顯示視窗
namedWindow("Src_gray");
imshow("Src_gray", src_gray);
灰度圖 |
Step 4.
二值化
// 二值化
threshold( src_gray, threshold_output, 240, 255, THRESH_BINARY);
namedWindow("Undo Erode And Dilate");
imshow("Undo Erode And Dilate", threshold_output);
二值化 |
Step 5.
腐蝕即膨脹,將太小的物件排除
void Erosion(int, void*);
void Dilation(int, void*);
void Erosion(int, void*)
{
int erosion_type = 0;
if (erosion_elem == 0) {
erosion_type = MORPH_RECT;
} else if (erosion_elem == 1) {
erosion_type = MORPH_CROSS;
} else if (erosion_elem == 2) {
erosion_type = MORPH_ELLIPSE;
}
Mat element = getStructuringElement(erosion_type,
Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size));
erode(threshold_output, threshold_output, element);
imshow("Erosion", threshold_output);
}
void Dilation(int, void*)
{
int dilation_type = 0;
if (dilation_elem == 0) {
dilation_type = MORPH_RECT;
} else if (dilation_elem == 1){
dilation_type = MORPH_CROSS;
} else if (dilation_elem == 2) {
dilation_type = MORPH_ELLIPSE;
}
Mat element = getStructuringElement(dilation_type,
Size(2 * dilation_size + 1, 2 * dilation_size + 1),
Point(dilation_size, dilation_size));
dilate(threshold_output, threshold_output, element);
imshow("Dilation", threshold_output);
}
Erosion
Erosion(0, 0);
腐蝕 |
Dilation(0, 0);
膨脹 |
Step 6.
畫輪廓
vector<vector<Point> > contours, contoursFill;
vector<Vec4i> hierarchy;
findContours(threshold_output, contours, hierarchy,
CV_RETR_TREE, CHAIN_APPROX_NONE, Point(0, 0));
Mat drawing = Mat::zeros(src.size(), CV_8UC3);
int parentIdx=-1;
int k = 0;
for( int i = 0; i < contours.size(); i++ ) {
parentIdx = i;
contoursFill.push_back(contours[parentIdx]);
// 畫輪廓
drawContours(drawing, contours, parentIdx, CV_RGB(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)) , 1, 8);
}
namedWindow("畫輪廓");
imshow("畫輪廓", drawing );
畫輪廓 |
Step 7.
填滿輪廓顏色
// 填滿輪廓顏色
for(int i = 0; i < contoursFill.size(); i++) {
drawContours(drawingFill, contoursFill, i, CV_RGB(rng.uniform(100,255), rng.uniform(100,255), rng.uniform(100,255)) , -1, 4, hierarchy[k][2], 0, Point() );
}
namedWindow("填滿輪廓顏色");
imshow("填滿輪廓顏色", drawingFill );
填滿輪廓顏色 |
Step 8.
圈出紅色方框
// 紅色方框顯示
Mat gray_all,threshold_output_all;
vector<vector<Point> > contours_all;
vector<Vec4i> hierarchy_all;
cvtColor( drawingFill, gray_all, CV_BGR2GRAY );
threshold( gray_all, threshold_output_all, 45, 255, THRESH_BINARY );
// RETR_EXTERNAL 尋找最外層
findContours( threshold_output_all, contours_all, hierarchy_all, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0) );
for(int j = 0 ; j < contours_all.size() ; j++) {
Point2f fourPoint2f[4];
RotatedRect rectPoint = minAreaRect(contours_all[j]);
rectPoint.points(fourPoint2f);
for (int i = 0; i < 4 ; i++) {
line(src_result, fourPoint2f[i%4], fourPoint2f[(i + 1)%4],
Scalar(20,21,237), 3);
}
}
namedWindow("Result");
imshow("Result", src_result);
cvWaitKey();
return 0;
調整腐蝕和膨脹參數,圈出單一個物件
調整參數 |
原本一個燈泡會圈出兩個物件,調整成圈出一個物件
結果 |
後記
如果這篇文章對於你有幫助,可以幫忙分享給更多的人.文章內容如果有誤,可以在下方留言告知.本網站主要提供程式, 玩具相關資訊,可以訂閱獲得最即時的資訊.
留言
張貼留言