欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

OpenCV 圓與矩形識(shí)別的方法

 更新時(shí)間:2019年07月01日 14:28:48   作者:走在冷風(fēng)中c  
這篇文章主要介紹了OpenCV 圓與矩形識(shí)別的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

最近一個(gè)項(xiàng)目用到了圖像識(shí)別,之前從未接觸過(guò)OpenCV,經(jīng)過(guò)各種找教程,終于是搞懂了一些。

整個(gè)具體流程大概是獲取圖像-->圖像二值化,灰度圖(cvtColor)-->圖像降噪(GaussianBlur)->輪廓識(shí)別(cvFindContours)-->形狀判斷。

大多數(shù)教程很專業(yè),各種參數(shù)分析看不懂,經(jīng)過(guò)各種搜索終于是搞懂了。

識(shí)別圓

在識(shí)別圓方面,OpenCV有內(nèi)置的方法:霍夫圓變化:

HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);

參數(shù)分析:

edges:灰度圖像

circles: std::vector<Vec3f> circles;數(shù)組,用來(lái)存儲(chǔ)圓的坐標(biāo)信息

CV_HOUGH_GRADIENT:Hough 變換方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in [Yuen03].默認(rèn)用這個(gè)

1.5:累加器圖像的分辨率,1的時(shí)候是與獲取到的圖像相同,1.5就是1.5倍

10:圓與圓的最小距離,兩個(gè)圓心距離如果在范圍內(nèi)則被認(rèn)定為1個(gè)圓

200:100-200兩個(gè)參數(shù)選就夠了

100:默認(rèn)100,數(shù)值越低識(shí)別圓越不精確(圓的數(shù)量識(shí)別變多可能有個(gè)弧線就被識(shí)別是圓)

最后兩個(gè)參數(shù)分別是識(shí)別 圓的最小,最大的面積。

矩形識(shí)別

矩形識(shí)別并沒(méi)有內(nèi)置方法,需要自己手寫。

最主要的方法是二值化。通過(guò)二值化來(lái)調(diào)節(jié)識(shí)別的強(qiáng)度。

cvThreshold(tgray, gray, 75, 250, CV_THRESH_BINARY);

參數(shù)分析:

src:原始數(shù)組 (單通道 , 8-bit of 32-bit 浮點(diǎn)數(shù))。

dst:輸出數(shù)組,必須與 src 的類型一致,或者為 8-bit。

threshold:閾值

max_value:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。

threshold_type:閾值類型

threshold_type=CV_THRESH_BINARY:如果 src(x,y)>threshold ,dst(x,y) = max_value; 否則,dst(x,y)=0;

threshold_type=CV_THRESH_BINARY_INV:如果 src(x,y)>threshold,dst(x,y) = 0; 否則,dst(x,y) = max_value.

threshold_type=CV_THRESH_TRUNC:如果 src(x,y)>threshold,dst(x,y) = max_value; 否則dst(x,y) = src(x,y).

threshold_type=CV_THRESH_TOZERO:如果src(x,y)>threshold,dst(x,y) = src(x,y) ; 否則 dst(x,y) = 0。

threshold_type=CV_THRESH_TOZERO_INV:如果 src(x,y)>threshold,dst(x,y) = 0 ; 否則dst(x,y) = src(x,y).

效果圖如下:

在矩形識(shí)別里面的二值化圖:

圓識(shí)別:

源碼:

#include <opencv2/opencv.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <WINSOCK2.H>
#include<iostream>
#include<thread>
#include <winsock2.h>
#include <stdio.h>
#include<string>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#include<vector>
 
using namespace cv;
 
 
   //////////////////////////////////////////////////////////////////
   //函數(shù)功能:用向量來(lái)做COSα=兩向量之積/兩向量模的乘積求兩條線段夾角
   //輸入:  線段3個(gè)點(diǎn)坐標(biāo)pt1,pt2,pt0,最后一個(gè)參數(shù)為公共點(diǎn)
   //輸出:  線段夾角,單位為角度
   //////////////////////////////////////////////////////////////////
double angle(CvPoint* pt1, CvPoint* pt2, CvPoint* pt0)
{
 double dx1 = pt1->x - pt0->x;
 double dy1 = pt1->y - pt0->y;
 double dx2 = pt2->x - pt0->x;
 double dy2 = pt2->y - pt0->y;
 double angle_line = (dx1*dx2 + dy1 * dy2) / sqrt((dx1*dx1 + dy1 * dy1)*(dx2*dx2 + dy2 * dy2) + 1e-10);//余弦值
 return acos(angle_line) * 180 / 3.141592653;
}
//////////////////////////////////////////////////////////////////
//函數(shù)功能:采用多邊形檢測(cè),通過(guò)約束條件尋找矩形
//輸入:  img 原圖像
//     storage 存儲(chǔ)
//     minarea,maxarea 檢測(cè)矩形的最小/最大面積
//     minangle,maxangle 檢測(cè)矩形邊夾角范圍,單位為角度
//輸出:  矩形序列
//////////////////////////////////////////////////////////////////
CvSeq* findSquares4(IplImage* img, CvMemStorage* storage, int minarea, int maxarea, int minangle, int maxangle, int(&temp)[30])
{
 CvSeq* contours;//邊緣
 int N = 6; //閾值分級(jí)
 CvSize sz = cvSize(img->width & -2, img->height & -2);
 IplImage* timg = cvCloneImage(img);//拷貝一次img
 IplImage* gray = cvCreateImage(sz, 8, 1); //img灰度圖
 IplImage* pyr = cvCreateImage(cvSize(sz.width / 2, sz.height / 2), 8, 3); //金字塔濾波3通道圖像中間變量
 IplImage* tgray = cvCreateImage(sz, 8, 1); ;
 CvSeq* result;
 double s, t;
 int sk = 0;
 CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage);
 
 cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height));
 //金字塔濾波 
 cvPyrDown(timg, pyr, 7);
 cvPyrUp(pyr, timg, 7);
 //在3個(gè)通道中尋找矩形 
 for (int c = 0; c < 3; c++) //對(duì)3個(gè)通道分別進(jìn)行處理 
 {
 cvSetImageCOI(timg, c + 1);
 cvCopy(timg, tgray, 0); //依次將BGR通道送入tgray     
 for (int l = 0; l < N; l++)
 {
  //不同閾值下二值化
  cvThreshold(tgray, gray, 75, 250, CV_THRESH_BINARY);
  cvShowImage("111", gray);
  cvFindContours(gray, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
  while (contours)
  { //多邊形逼近       
  result = cvApproxPoly(contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0);
 
  //如果是凸四邊形并且面積在范圍內(nèi) 
  if (result->total == 4 && fabs(cvContourArea(result, CV_WHOLE_SEQ)) > minarea && fabs(cvContourArea(result, CV_WHOLE_SEQ)) < maxarea && cvCheckContourConvexity(result))
  {
 
   s = 0;
   //判斷每一條邊
   for (int i = 0; i < 5; i++)
   {
   if (i >= 2)
   {  //角度      
    t = fabs(angle((CvPoint*)cvGetSeqElem(result, i), (CvPoint*)cvGetSeqElem(result, i - 2), (CvPoint*)cvGetSeqElem(result, i - 1)));
    s = s > t ? s : t;
   }
   }
   //這里的S為直角判定條件 單位為角度
   if (s > minangle && s < maxangle)
   {
   for (int i = 0; i < 4; i++)
    cvSeqPush(squares, (CvPoint*)cvGetSeqElem(result, i));
   CvRect rect = cvBoundingRect(contours, 1);    // 獲取矩形邊界框 
   CvPoint p1;
   p1 = cvPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);  //矩形中心坐標(biāo) 
   std::cout << "X:" << p1.x << "Y:" << p1.y << std::endl;
   }
  }
  contours = contours->h_next;
  }
 }
 std::cout << "圓的數(shù)量是"<<sk << std::endl;
 temp[26] = sk;
 
 
 sk = 0;
 }
 cvReleaseImage(&gray);
 cvReleaseImage(&pyr);
 cvReleaseImage(&tgray);
 cvReleaseImage(&timg);
 
 return squares;
}
//////////////////////////////////////////////////////////////////
//函數(shù)功能:畫(huà)出所有矩形
//輸入:  img 原圖像
//     squares 矩形序列
//     wndname 窗口名稱
//輸出:  圖像中標(biāo)記矩形
//////////////////////////////////////////////////////////////////
void drawSquares(IplImage* img, CvSeq* squares, const char* wndname)
{
 CvSeqReader reader;
 IplImage* cpy = cvCloneImage(img);
 CvPoint pt[4];
 int i;
 cvStartReadSeq(squares, &reader, 0);
 for (i = 0; i < squares->total; i += 4)
 {
 CvPoint* rect = pt;
 int count = 4;
 memcpy(pt, reader.ptr, squares->elem_size);
 CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
 memcpy(pt + 1, reader.ptr, squares->elem_size);
 CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
 memcpy(pt + 2, reader.ptr, squares->elem_size);
 CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
 memcpy(pt + 3, reader.ptr, squares->elem_size);
 CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
 //cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
 cvPolyLine(cpy, &rect, &count, 1, 1, CV_RGB(rand() & 255, rand() & 255, rand() & 255), 1, CV_AA, 0);//彩色繪制
 }
 cvShowImage("22", cpy);
 cvReleaseImage(&cpy);
}
 
void SendMessageOne()
{
 //開(kāi)起攝像頭
 VideoCapture capture;
 capture.open(0);
 Mat edges; //定義轉(zhuǎn)化的灰度圖
 if (!capture.isOpened())
 namedWindow("【效果圖】", CV_WINDOW_NORMAL);
 const char* winn = "1111";
 if (!capture.isOpened())
 //namedWindow(winn, CV_WINDOW_NORMAL);
 CvMemStorage* storage = 0;
 CvMemStorage* storage = 0;
 storage = cvCreateMemStorage(0);
 while (1)
 {
 int Y=0, J=0;
 Mat frame;
 capture >> frame;
 IplImage img0 = frame;
 //drawSquares(&img0, findSquares4(&img0, storage, 100, 2000, 80, 100, a), winn);
 //cvClearMemStorage(storage); //清空存儲(chǔ)
 Mat E = frame(Range(1, 320), Range(1, 240));
 cvtColor(frame, edges, CV_BGR2GRAY);
 //高斯濾波
 GaussianBlur(edges, edges, Size(7, 7), 2, 2);
 std::vector<Vec3f> circles;//存儲(chǔ)每個(gè)圓的位置信息
      //霍夫圓
 HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 100, 100, 0, 50);
 for (size_t i = 0; i < circles.size(); i++)
 {
  Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
  int radius = cvRound(circles[i][2]);
  //std::cout << "圓的X是" << circles[i][0] << "圓的Y是" << circles[i][1] << std:: endl;
  //繪制圓輪廓 
  circle(frame, center, radius, Scalar(155, 50, 255), 3, 8, 0);
  int R = frame.at<Vec3b>(cvRound(circles[i][1]), cvRound(circles[i][0]))[2];//R
  int G = frame.at<Vec3b>(cvRound(circles[i][1]), cvRound(circles[i][0]))[1];//G
  int B = frame.at<Vec3b>(cvRound(circles[i][1]), cvRound(circles[i][0]))[0];//B
  int num = R + G + B;
  std::cout << "圓心顏色是" << num << std::endl;
        }
 
 imshow("【效果圖】", frame);
 waitKey(30);
 }
}
 
int main()
{
 std::thread *a = new std::thread(SendMessageOne);
 a->join();
 
 return 0;
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C/C++中數(shù)據(jù)類型轉(zhuǎn)換詳解及其作用介紹

    C/C++中數(shù)據(jù)類型轉(zhuǎn)換詳解及其作用介紹

    這篇文章主要介紹了C/C++中數(shù)據(jù)類型轉(zhuǎn)換詳解及其作用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • 詳解C++ 桶排序(BucketSort)

    詳解C++ 桶排序(BucketSort)

    這篇文章主要介紹了C++桶排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 教你用Matlab制作立體動(dòng)態(tài)相冊(cè)

    教你用Matlab制作立體動(dòng)態(tài)相冊(cè)

    沒(méi)想到吧,MATLAB竟也能制作3D相冊(cè)!本文將為大家詳細(xì)介紹Matlab制作立體動(dòng)態(tài)相冊(cè)的方法步驟,感興趣的小伙伴可以跟隨小編一起動(dòng)手試一試
    2022-03-03
  • 如何在C語(yǔ)言中判斷socket是否已經(jīng)斷開(kāi)

    如何在C語(yǔ)言中判斷socket是否已經(jīng)斷開(kāi)

    如果不主動(dòng)關(guān)閉socket的話,系統(tǒng)不會(huì)自動(dòng)關(guān)閉的,除非當(dāng)前進(jìn)程掛掉了,操作系統(tǒng)把占用的socket回收了才會(huì)關(guān)閉。小編今天跟大家簡(jiǎn)單介紹下如何在C語(yǔ)言中判斷socket是否已經(jīng)斷開(kāi)
    2019-05-05
  • 一文解析C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理

    一文解析C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • 用C語(yǔ)言winform編寫滲透測(cè)試工具實(shí)現(xiàn)SQL注入功能

    用C語(yǔ)言winform編寫滲透測(cè)試工具實(shí)現(xiàn)SQL注入功能

    本篇文章主要介紹使用C#winform編寫滲透測(cè)試工具,實(shí)現(xiàn)SQL注入的功能。使用python編寫SQL注入腳本,基于get顯錯(cuò)注入的方式進(jìn)行數(shù)據(jù)庫(kù)的識(shí)別、獲取表名、獲取字段名,最終獲取用戶名和密碼;使用C#winform編寫windows客戶端軟件調(diào)用.py腳本,實(shí)現(xiàn)用戶名和密碼的獲取
    2021-08-08
  • C++?Boost?Lambda表達(dá)式詳解

    C++?Boost?Lambda表達(dá)式詳解

    Lambda?表達(dá)式(lambda?expression)是一個(gè)匿名函數(shù),Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名。本文就來(lái)為大家詳細(xì)講講C++中Lambda表達(dá)式的使用,需要的可以參考一下
    2022-11-11
  • C語(yǔ)言常見(jiàn)排序算法之交換排序(冒泡排序,快速排序)

    C語(yǔ)言常見(jiàn)排序算法之交換排序(冒泡排序,快速排序)

    這篇文章主要介紹了C語(yǔ)言常見(jiàn)排序算法之交換排序(冒泡排序,快速排序),冒泡排序即Bubble?Sort,類似于水中冒泡,較大的數(shù)沉下去,較小的數(shù)慢慢冒起來(lái),假設(shè)從小到大,即為較大的數(shù)慢慢往后排,較小的數(shù)慢慢往前排
    2022-07-07
  • C語(yǔ)言實(shí)現(xiàn)2048小游戲

    C語(yǔ)言實(shí)現(xiàn)2048小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)2048小游戲,注釋清晰,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • C語(yǔ)言連接并操作Sedna XML數(shù)據(jù)庫(kù)的方法

    C語(yǔ)言連接并操作Sedna XML數(shù)據(jù)庫(kù)的方法

    這篇文章主要介紹了C語(yǔ)言連接并操作Sedna XML數(shù)據(jù)庫(kù)的方法,實(shí)例分析了C語(yǔ)言操作XML文件的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06

最新評(píng)論