在計算機視覺領域,形狀識別是一個非常重要的任務。通過識別圖像中的形狀,我們可以實現物體檢測、目標跟蹤、圖像分割等多種應用。OpenCV 是一個功能強大的開源計算機視覺庫,提供了豐富的圖像處理和計算機視覺算法。本文將詳細介紹如何使用 C++ 和 OpenCV 實現形狀識別功能。
在開始之前,我們需要確保已經安裝了 OpenCV 庫。如果還沒有安裝,可以參考 OpenCV 的官方文檔進行安裝。
在 Ubuntu 系統上,可以使用以下命令安裝 OpenCV:
sudo apt-get update
sudo apt-get install libopencv-dev
在 Windows 系統上,可以從 OpenCV 官網下載預編譯的庫,并配置開發環境。
創建一個新的 C++ 項目,并在項目中包含 OpenCV 的頭文件和庫文件。例如,在 CMake 項目中,可以這樣配置 CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(ShapeRecognition)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(ShapeRecognition main.cpp)
target_link_libraries(ShapeRecognition ${OpenCV_LIBS})
在進行形狀識別之前,通常需要對圖像進行一些預處理操作,以提高識別的準確性。常見的預處理步驟包括灰度化、二值化、去噪等。
首先,我們需要讀取一張圖像??梢允褂?OpenCV 的 imread 函數來讀取圖像:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
cv::Mat image = cv::imread("image.jpg");
if (image.empty()) {
std::cerr << "Could not open or find the image!" << std::endl;
return -1;
}
cv::imshow("Original Image", image);
cv::waitKey(0);
return 0;
}
將彩色圖像轉換為灰度圖像可以減少計算量,并且在一些情況下可以提高形狀識別的效果??梢允褂?cvtColor 函數將圖像轉換為灰度圖像:
cv::Mat grayImage;
cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
cv::imshow("Gray Image", grayImage);
cv::waitKey(0);
二值化是將灰度圖像轉換為黑白圖像的過程??梢允褂?threshold 函數進行二值化:
cv::Mat binaryImage;
cv::threshold(grayImage, binaryImage, 128, 255, cv::THRESH_BINARY);
cv::imshow("Binary Image", binaryImage);
cv::waitKey(0);
去噪是為了去除圖像中的噪聲,使得形狀更加清晰??梢允褂?GaussianBlur 函數進行高斯模糊:
cv::Mat blurredImage;
cv::GaussianBlur(binaryImage, blurredImage, cv::Size(5, 5), 0);
cv::imshow("Blurred Image", blurredImage);
cv::waitKey(0);
在圖像預處理之后,我們可以開始進行形狀檢測。OpenCV 提供了多種方法來檢測圖像中的形狀,常用的方法包括輪廓檢測和霍夫變換。
輪廓檢測是檢測圖像中物體邊界的一種方法??梢允褂?findContours 函數來檢測圖像中的輪廓:
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(blurredImage, contours, hierarchy, cv::RETR_TREE, cv::CHN_APPROX_SIMPLE);
cv::Mat contourImage = cv::Mat::zeros(blurredImage.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++) {
cv::drawContours(contourImage, contours, i, cv::Scalar(0, 255, 0), 2);
}
cv::imshow("Contours", contourImage);
cv::waitKey(0);
通過檢測到的輪廓,我們可以進一步識別出圖像中的形狀。常見的形狀包括圓形、矩形、三角形等??梢酝ㄟ^計算輪廓的幾何特性來識別形狀。
識別圓形可以使用 minEnclosingCircle 函數來計算輪廓的最小外接圓:
for (size_t i = 0; i < contours.size(); i++) {
cv::Point2f center;
float radius;
cv::minEnclosingCircle(contours[i], center, radius);
if (radius > 10) { // 過濾掉太小的圓
cv::circle(contourImage, center, radius, cv::Scalar(255, 0, 0), 2);
}
}
cv::imshow("Circles", contourImage);
cv::waitKey(0);
識別矩形可以使用 approxPolyDP 函數來近似輪廓的多邊形,并判斷是否為矩形:
for (size_t i = 0; i < contours.size(); i++) {
std::vector<cv::Point> approx;
cv::approxPolyDP(contours[i], approx, cv::arcLength(contours[i], true) * 0.02, true);
if (approx.size() == 4) { // 判斷是否為四邊形
cv::drawContours(contourImage, std::vector<std::vector<cv::Point>>{approx}, -1, cv::Scalar(0, 0, 255), 2);
}
}
cv::imshow("Rectangles", contourImage);
cv::waitKey(0);
識別三角形可以通過判斷輪廓的頂點數是否為 3:
for (size_t i = 0; i < contours.size(); i++) {
std::vector<cv::Point> approx;
cv::approxPolyDP(contours[i], approx, cv::arcLength(contours[i], true) * 0.02, true);
if (approx.size() == 3) { // 判斷是否為三角形
cv::drawContours(contourImage, std::vector<std::vector<cv::Point>>{approx}, -1, cv::Scalar(255, 255, 0), 2);
}
}
cv::imshow("Triangles", contourImage);
cv::waitKey(0);
霍夫變換是一種用于檢測圖像中直線、圓等幾何形狀的方法。OpenCV 提供了 HoughLines 和 HoughCircles 函數來檢測直線和圓。
可以使用 HoughLines 函數來檢測圖像中的直線:
std::vector<cv::Vec2f> lines;
cv::HoughLines(blurredImage, lines, 1, CV_PI / 180, 150);
cv::Mat lineImage = cv::Mat::zeros(blurredImage.size(), CV_8UC3);
for (size_t i = 0; i < lines.size(); i++) {
float rho = lines[i][0], theta = lines[i][1];
cv::Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a * rho, y0 = b * rho;
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * (a));
cv::line(lineImage, pt1, pt2, cv::Scalar(0, 0, 255), 2);
}
cv::imshow("Lines", lineImage);
cv::waitKey(0);
可以使用 HoughCircles 函數來檢測圖像中的圓:
std::vector<cv::Vec3f> circles;
cv::HoughCircles(blurredImage, circles, cv::HOUGH_GRADIENT, 1, blurredImage.rows / 8, 200, 100, 0, 0);
cv::Mat circleImage = cv::Mat::zeros(blurredImage.size(), CV_8UC3);
for (size_t i = 0; i < circles.size(); i++) {
cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
cv::circle(circleImage, center, radius, cv::Scalar(0, 255, 0), 2);
}
cv::imshow("Circles", circleImage);
cv::waitKey(0);
在完成形狀識別之后,我們可以將識別結果展示出來??梢詫⒆R別到的形狀在原圖上標注出來,以便直觀地查看識別效果。
cv::Mat resultImage = image.clone();
for (size_t i = 0; i < contours.size(); i++) {
std::vector<cv::Point> approx;
cv::approxPolyDP(contours[i], approx, cv::arcLength(contours[i], true) * 0.02, true);
if (approx.size() == 3) {
cv::drawContours(resultImage, std::vector<std::vector<cv::Point>>{approx}, -1, cv::Scalar(255, 255, 0), 2);
} else if (approx.size() == 4) {
cv::drawContours(resultImage, std::vector<std::vector<cv::Point>>{approx}, -1, cv::Scalar(0, 0, 255), 2);
} else {
cv::Point2f center;
float radius;
cv::minEnclosingCircle(contours[i], center, radius);
if (radius > 10) {
cv::circle(resultImage, center, radius, cv::Scalar(255, 0, 0), 2);
}
}
}
cv::imshow("Result", resultImage);
cv::waitKey(0);
本文詳細介紹了如何使用 C++ 和 OpenCV 實現形狀識別功能。通過圖像預處理、輪廓檢測、形狀識別等步驟,我們可以有效地識別出圖像中的各種形狀。OpenCV 提供了豐富的函數和算法,使得形狀識別變得相對簡單。希望本文能夠幫助讀者理解和掌握形狀識別的基本方法,并在實際項目中應用這些技術。
通過以上步驟,您可以使用 C++ 和 OpenCV 實現基本的形狀識別功能。希望這篇文章對您有所幫助!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。