日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

opencv(十三)-快速连通区域分析

發布時間:2024/1/1 编程问答 69 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opencv(十三)-快速连通区域分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

索引目錄

  • 1.連通區域標記算法
  • 2.剔除小連通區域
  • 參考

1.連通區域標記算法

連接區域標記算法(connected component labeling algorithm)是圖像分析中最常用的算法之一,輸入要求是一張二值(黑白)圖像,屬于同一連通區域的非零像素都是同一定值,算法的實質是掃描一幅圖像的每個像素,由具有相同像素值的相鄰像素組成像素集合一個連通區域,對于找到的每個連通區域,我們賦予其一個唯一的標識(Label),以區別其他連通區域。常見的連通區域分析的算法分為兩類:

  • Two-Pass法
  • Seed-Filling種子填充法
    掃描是基于每個像素單位,對于二值圖像而言,連通區域集合可以是V={1|白色}或者V={0|黑色}, 取決于前景色與背景色的不同。對于灰度圖像來說,連圖區域像素集合可能是一系列在0 ~ 255之間k的灰度值。
    在背景分割算法中,連通區域分析常常被用作后處理濾波器,用于去掉小噪聲塊,也常用于OCR這一類含有已知前景待提取的問題中。通過連通區域的統計信息進行篩選。
  • 連通域分析更慢的手動方式是先調用findContours()(傳入cv::RETR_CCOMP標志),隨后在得到的連通域上循環調用cv::drawContours()。
    快速連通區域分析算法如下:

    //不帶統計信息的API及其解釋如下: int cv::connectedComponents( InputArray image, // 輸入二值圖像,黑色背景 OutputArray labels, // 輸出的標記圖像,背景index=0 int connectivity = 8, // 連通域,默認是8連通 int ltype = CV_32S // 輸出的labels類型,默認是CV_32S ) //帶有統計信息的API及其解釋如下: int cv::connectedComponentsWithStats( InputArray image, // 輸入二值圖像,黑色背景 OutputArray labels, // 輸出的標記圖像,背景index=0 OutputArray stats, // 統計信息,包括每個區域的位置、寬、高與面積 OutputArray centroids, // 每個組件的中心位置坐標cx, cy int connectivity, // 尋找連通組件算法的連通域,默認是8連通 int ltype, // 輸出的labels的Mat類型CV_32S int ccltype // 連通組件算法 )

    其中stats包括以下枚舉類型數據信息:
    CC_STAT_LEFT
    組件的左上角點像素點坐標的X位置.
    CC_STAT_TOP
    組件的左上角點像素點坐標的Y位置.
    CC_STAT_WIDTH
    組件外接矩形的寬度
    CC_STAT_HEIGHT
    組件外接矩形的高度.
    CC_STAT_AREA
    當前連通組件的面積(像素單位)

    #include <opencv2/opencv.hpp> #include <iostream>using namespace cv; using namespace std;RNG rng(12345); void connected_component_demo(Mat &image); void connected_component_stats_demo(Mat &image); int main(int argc, char** argv) {Mat src = imread("img/rice.png");if (src.empty()) {printf("could not load image...\n");}imshow("input", src);connected_component_stats_demo(src);waitKey(0);return 0; }void connected_component_demo(Mat &image) {// 二值化Mat gray, binary;cvtColor(image, gray, COLOR_BGR2GRAY);threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);// 形態學操作Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));morphologyEx(binary, binary, MORPH_OPEN, k);morphologyEx(binary, binary, MORPH_CLOSE, k);imshow("binary", binary);imwrite("D:/ccla_binary.png", binary);Mat labels = Mat::zeros(image.size(), CV_32S);int num_labels = connectedComponents(binary, labels, 8, CV_32S);printf("total labels : %d\n", (num_labels - 1));vector<Vec3b> colors(num_labels);// background colorcolors[0] = Vec3b(0, 0, 0);// object colorfor (int i = 1; i < num_labels; i++) {colors[i] = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));}// render resultMat dst = Mat::zeros(image.size(), image.type());int w = image.cols;int h = image.rows;for (int row = 0; row < h; row++) {for (int col = 0; col < w; col++) {int label = labels.at<int>(row, col);if (label == 0) continue;dst.at<Vec3b>(row, col) = colors[label];}}imshow("ccla-demo", dst);imwrite("D:/ccla_dst.png", dst); }void connected_component_stats_demo(Mat &image) {// 二值化Mat gray, binary;cvtColor(image, gray, COLOR_BGR2GRAY);threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);// 形態學操作Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));morphologyEx(binary, binary, MORPH_OPEN, k);morphologyEx(binary, binary, MORPH_CLOSE, k);imshow("binary", binary);Mat labels = Mat::zeros(image.size(), CV_32S);Mat stats, centroids;int num_labels = connectedComponentsWithStats(binary, labels, stats, centroids, 8, 4);printf("total labels : %d\n", (num_labels - 1));vector<Vec3b> colors(num_labels);// background colorcolors[0] = Vec3b(0, 0, 0);// object colorint b = rng.uniform(0, 256);int g = rng.uniform(0, 256);int r = rng.uniform(0, 256);for (int i = 1; i < num_labels; i++) {colors[i] = Vec3b(0, 255, 0);if (stats.at<int>(i - 1, cv::CC_STAT_AREA) < 1700)colors[i] = Vec3b(0, 0, 0);//小區域涂黑}// render resultMat dst = Mat::zeros(image.size(), image.type());int w = image.cols;int h = image.rows;for (int row = 0; row < h; row++) {for (int col = 0; col < w; col++) {int label = labels.at<int>(row, col);if (label == 0) continue;dst.at<Vec3b>(row, col) = colors[label];}}for (int i = 1; i < num_labels; i++) {Vec2d pt = centroids.at<Vec2d>(i, 0);int x = stats.at<int>(i, CC_STAT_LEFT);int y = stats.at<int>(i, CC_STAT_TOP);int width = stats.at<int>(i, CC_STAT_WIDTH);int height = stats.at<int>(i, CC_STAT_HEIGHT);int area = stats.at<int>(i, CC_STAT_AREA);printf("area : %d, center point(%.2f, %.2f)\n", area, pt[0], pt[1]);circle(dst, Point(pt[0], pt[1]), 2, Scalar(0, 0, 255), -1, 8, 0);rectangle(dst, Rect(x, y, width, height), Scalar(255, 0, 255), 1, 8, 0);}imshow("ccla-demo", dst);imwrite("D:/ccla_stats_dst.png", dst); }

    2.剔除小連通區域

    剔除小面積連通區域在二值圖像連通區域分析時很有用,之前做的使用采用了for循環的形式,可以使用vector.erase(std::remove_if())的方法, 結合lambda表達式直接剔除。
    統計二值圖像的連通區域通過cv::findcontours()實現,二值圖像輪廓的容器是std::vector。連通區域的面積可以由函數cv::contourArea()得到。
    剔除小面積連通區域后,可以使用函數cv::drawContours()函數將輪廓畫出,將其第三個參數設置為-1為畫所有輪廓,將其第5個參數設置為cv::FILLED設置為填充。則可以得到剔除后小面積連通后的二值圖像。

    #include <opencv2/opencv.hpp> #include <vector> #include <algorithm> int main() {cv::Mat img = cv::imread("img/pill_002.png");cv::Mat imgG(img.size(), img.type());cv::cvtColor(img, imgG, cv::COLOR_BGR2GRAY);cv::threshold(imgG, imgG, 50, 255, cv::THRESH_BINARY);std::string win1 = "original mask"; std::string win2 = "after remove";cv::namedWindow(win1); cv::moveWindow(win1, 10, 10);cv::namedWindow(win2); cv::moveWindow(win2, 800, 10);cv::imshow(win1, imgG);cv::waitKey(0); cv::destroyWindow(win1); // 提取連通區域,并剔除小面積聯通區域std::vector<std::vector<cv::Point>> contours;cv::findContours(imgG, contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);contours.erase(std::remove_if(contours.begin(), contours.end(),[](const std::vector<cv::Point>& c) {return cv::contourArea(c) < 3000; }),contours.end());// 顯示圖像并保存imgG.setTo(0);cv::drawContours(imgG, contours, -1, cv::Scalar(255), cv::FILLED);cv::imshow(win2, imgG);cv::waitKey(0); cv::destroyWindow(win2); return 0; }

    參考

    1.https://blog.csdn.net/jia20003/article/details/80662396
    2.https://www.cnblogs.com/zi-wang/p/9800141.html

    總結

    以上是生活随笔為你收集整理的opencv(十三)-快速连通区域分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。