1. 程式人生 > >opencv——檢測四邊形的四個角點(二)

opencv——檢測四邊形的四個角點(二)

#include "stdio.h"  
#include "cv.h"  
#include "highgui.h"  
#include "Math.h"
#define max_corners 4


int Otsu(IplImage* src);

int main(int argc, char*argv[])
{
    IplImage* img = cvLoadImage("C:\\Users\\aoe\\Desktop\\the last\\20160716_3DMeasurement\\1.jpg", 0);
    cvNamedWindow("img", 1);
    cvShowImage("img"
, img); double sum = 0.0;//求影象灰度平均值 for (int y = 0; y < img->height; y++) { for (int x = 0; x < img->width; x++) { CvScalar cs = { 0.0 }; cs=cvGet2D(img, y, x); sum += cs.val[0]; } } double average = 0.0;//as.val[0]是double型別的資料 average = sum / ((img->height)*(
img->width)); printf("sum=%lf\n", sum); printf("average=%lf\n", average); IplImage* aver = cvCreateImage(cvGetSize(img), 8, 1);//生成一幅畫素值均為上一幅影象的畫素的均值的影象 for (int y = 0; y < aver->height; y++) { for (int x = 0; x < aver->width; x++) { CvScalar cs = { 0
.0 }; cs.val[0]=average; cvSet2D(aver, y, x,cs); } } cvNamedWindow("aver", 1); cvShowImage("aver", aver); IplImage* next = cvCreateImage(cvGetSize(img), 8, 1);//生成一幅畫素值減去影象畫素的均值的影象 for (int y = 0; y < next->height; y++) { for (int x = 0; x < next->width; x++) { CvScalar cs = {0.0}; cs = cvGet2D(img, y, x); CvScalar ds = { 0.0 }; if (cs.val[0] > average) ds.val[0] = average; else ds.val[0] = cs.val[0]; cvSet2D(next, y, x, ds); } } cvNamedWindow("next", 1); cvShowImage("next", next); IplImage* dst = cvCreateImage(cvGetSize(img), 8, 1); int threshold = Otsu(next);//最大類間方差閾值分割 printf("threshold = %d\n", threshold); cvThreshold(next, dst, threshold, 255, CV_THRESH_BINARY); cvNamedWindow("dst", 1); cvShowImage("dst", dst); /* IplImage* im_median_filter = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); cvSmooth(dst, im_median_filter, CV_MEDIAN, 3);//中值濾波 cvNamedWindow("im_median_filter", 1); cvShowImage("im_median_filter", im_median_filter);*/ CvRect roi = cvRect(30, 30, 120, 120);//去除複雜背景 IplImage* img1 = cvCreateImage(cvGetSize(dst), dst->depth, dst->nChannels); for (int y = 0; y < img1->height; y++) { for (int x = 0; x < img1->width; x++) { CvScalar cs = (255); cvSet2D(img1, y, x, cs); } } CvRect roi1 = cvRect(30, 30, 120, 120); cvNamedWindow("img1"); cvShowImage("img1", img1); cvSetImageROI(dst, roi); cvSetImageROI(img1, roi1); cvCopy(dst, img1); cvResetImageROI(dst); cvResetImageROI(img1); cvNamedWindow("result", 1); cvShowImage("result", img1); IplImage*edge = cvCreateImage(cvGetSize(img), 8, 1);//canny邊緣檢測 int edgeThresh = 1; cvCanny(img1, edge, edgeThresh, edgeThresh * 3, 3); cvNamedWindow("canny", 1); cvShowImage("canny", edge); int count = 0; for (int yy = 0; yy < edge->height; yy++)//統計邊緣影象中共有多少個黑色畫素點 { for (int xx = 0; xx < edge->width; xx++) { //CvScalar ss = (255); double ds = cvGet2D(edge, yy, xx).val[0]; if (ds == 0) count++; } } int dianshu_threshold = (176 * 144 - count) / 4;//將白色畫素點數的四分之一作為hough變換的閾值 IplImage* houghtu = cvCreateImage(cvGetSize(edge), IPL_DEPTH_8U, 1);//hough直線變換 CvMemStorage*storage = cvCreateMemStorage(); CvSeq*lines = 0; int i, j, k, m, n; while (true)//迴圈找出合適的閾值,使檢測到的直線的數量在8-12之間 { lines = cvHoughLines2(edge, storage, CV_HOUGH_STANDARD, 1, CV_PI / 180, dianshu_threshold, 0, 0); int line_number = lines->total; if (line_number <8) { dianshu_threshold = dianshu_threshold - 2; } else if (line_number > 12) { dianshu_threshold = dianshu_threshold + 1; } else { printf("line_number=%d\n", line_number); break; } } int A = 1; double B = CV_PI / 180; while (1) { for (i = 0; i <lines->total; i++)//將多條非常相像的直線剔除 { for (j = 0; j < lines->total; j++) { if (j != i) { float*line1 = (float*)cvGetSeqElem(lines, i); float*line2 = (float*)cvGetSeqElem(lines, j); float rho1 = line1[0]; float threta1 = line1[1]; float rho2 = line2[0]; float threta2 = line2[1]; if (abs(rho1 - rho2) < A && abs(threta1 - threta2) < B) cvSeqRemove(lines, j); } } } printf("lines->total=%d\n", lines->total); if ((lines->total > 4)&&(A<8))//剔除一圈後如何直線的數量大於4,則改變A和B,繼續刪除相似的直線 { A = A + 1; B = B + CV_PI / 180; } else { printf("lines->total=%d\n", lines->total); break; } } for (k = 0; k < lines->total; k++)//畫出直線 { float*line = (float*)cvGetSeqElem(lines, k); float rho = line[0];//r=line[0] float threta = line[1];//threta=line[1] CvPoint pt1, pt2; double a = cos(threta), b = sin(threta); double x0 = a*rho; double y0 = b*rho; pt1.x = cvRound(x0 + 100 * (-b));//定義直線的終點和起點,直線上每一個點應該滿足直線方程r=xcos(threta)+ysin(threta); pt1.y = cvRound(y0 + 100 * (a)); pt2.x = cvRound(x0 - 1200 * (-b)); pt2.y = cvRound(y0 - 1200 * (a)); cvLine(houghtu, pt1, pt2, CV_RGB(0, 255, 255), 1, 8); } const double C = CV_PI / 3; const double D = CV_PI / 1.5; int num = 0; CvPoint arr[12] = { { 0, 0 } }; for (m = 0; m < lines->total; m++)//畫出直線的交點 { for (n = 0; n < lines->total; n++) { if (n != m) { float*Line1 = (float*)cvGetSeqElem(lines, m); float*Line2 = (float*)cvGetSeqElem(lines, n); float Rho1 = Line1[0]; float Threta1 = Line1[1]; float Rho2 = Line2[0]; float Threta2 = Line2[1]; if ((abs(Threta1 - Threta2) > C) && (abs(Threta1 - Threta2) <D)) { double a1 = cos(Threta1), b1 = sin(Threta1); double a2 = cos(Threta2), b2 = sin(Threta2); CvPoint pt; pt.x = (Rho2*b1 - Rho1*b2) / (a2*b1 - a1*b2);//直線交點公式 pt.y = (Rho1 - a1*pt.x) / b1; cvCircle(houghtu, pt, 3, CV_RGB(255, 255, 0)); arr[num++] = pt;//將點的座標儲存在一個數組中 } } } } printf("num=%d\n", num); printf("arr[0].x=%d\n", arr[0].x); printf("arr[0].y=%d\n", arr[0].y); printf("arr[1].x=%d\n", arr[1].x); printf("arr[1].y=%d\n", arr[1].y); printf("arr[2].x=%d\n", arr[2].x); printf("arr[2].y=%d\n", arr[2].y); printf("arr[3].x=%d\n", arr[3].x); printf("arr[3].y=%d\n", arr[3].y); printf("arr[4].x=%d\n", arr[4].x); printf("arr[4].y=%d\n", arr[4].y); printf("arr[5].x=%d\n", arr[5].x); printf("arr[5].y=%d\n", arr[5].y); printf("arr[6].x=%d\n", arr[6].x); printf("arr[6].y=%d\n", arr[6].y); printf("arr[7].x=%d\n", arr[7].x); printf("arr[7].y=%d\n", arr[7].y); printf("arr[8].x=%d\n", arr[8].x); printf("arr[8].y=%d\n", arr[8].y); printf("arr[9].x=%d\n", arr[9].x); printf("arr[9].y=%d\n", arr[9].y); printf("arr[10].x=%d\n", arr[10].x); printf("arr[10].y=%d\n", arr[10].y); printf("arr[11].x=%d\n", arr[11].x); printf("arr[11].y=%d\n", arr[11].y); CvPoint arr1[12] = { { 0, 0 } };//將重複的角點剔除 int num1 = 0; for (int r = 0; r < 12; r++) { int s = 0; for (; s < num1; s++) { if (abs(arr[r].x - arr1[s].x) <= 2 && abs(arr[r].y - arr1[s].y) <= 2) break; } if (s == num1) { arr1[num1] = arr[r]; num1++; } } printf("num1=%d\n", num1); printf("arr1[0].x=%d\n", arr1[0].x); printf("arr1[0].y=%d\n", arr1[0].y); printf("arr1[1].x=%d\n", arr1[1].x); printf("arr1[1].y=%d\n", arr1[1].y); printf("arr1[2].x=%d\n", arr1[2].x); printf("arr1[2].y=%d\n", arr1[2].y); printf("arr1[3].x=%d\n", arr1[3].x); printf("arr1[3].y=%d\n", arr1[3].y); printf("arr1[4].x=%d\n", arr1[4].x); printf("arr1[4].y=%d\n", arr1[4].y); printf("arr1[5].x=%d\n", arr1[5].x); printf("arr1[5].y=%d\n", arr1[5].y); printf("arr1[6].x=%d\n", arr1[6].x); printf("arr1[6].y=%d\n", arr1[6].y); printf("arr1[7].x=%d\n", arr1[7].x); printf("arr1[7].y=%d\n", arr1[7].y); printf("arr1[8].x=%d\n", arr1[8].x); printf("arr1[8].y=%d\n", arr1[8].y); printf("arr1[9].x=%d\n", arr1[9].x); printf("arr1[9].y=%d\n", arr1[9].y); printf("arr1[10].x=%d\n", arr1[10].x); printf("arr1[10].y=%d\n", arr1[10].y); printf("arr1[11].x=%d\n", arr1[11].x); printf("arr1[11].y=%d\n", arr1[11].y); for (int w = 0; w < 5; w++) { CvPoint ps; ps = arr1[w]; cvCircle(img, ps, 3, CV_RGB(255, 0, 0)); } cvNamedWindow("img", 1); cvShowImage("img", img); cvNamedWindow("houghtu", 1); cvShowImage("houghtu", houghtu); cvWaitKey(-1); cvReleaseImage(&img); //cvReleaseImage(&edge); return 0; } int Otsu(IplImage* src) { int height = src->height; int width = src->width; //histogram float histogram[256] = { 0 }; for (int i = 0; i < height; i++) { unsigned char* p = (unsigned char*)src->imageData + src->widthStep * i; for (int j = 0; j < width; j++) { histogram[*p++]++; } } //normalize histogram int size = height * width; for (int i = 0; i < 256; i++) { histogram[i] = histogram[i] / size; } //average pixel value float avgValue = 0; for (int i = 0; i < 256; i++) { avgValue += i * histogram[i]; //整幅影象的平均灰度 } int threshold; float maxVariance = 0; float w = 0, u = 0; for (int i = 0; i < 256; i++) { w += histogram[i]; //假設當前灰度i為閾值, 0~i 灰度的畫素(假設畫素值在此範圍的畫素叫做前景畫素) 所佔整幅影象的比例 u += i * histogram[i]; // 灰度i 之前的畫素(0~i)的平均灰度值: 前景畫素的平均灰度值 float t = avgValue * w - u; float variance = t * t / (w * (1 - w)); if (variance > maxVariance) { maxVariance = variance; threshold = i; } } return threshold; }

這裡寫圖片描述

相關推薦

opencv——檢測四邊形

#include "stdio.h" #include "cv.h" #include "highgui.h" #include "Math.h" #define max_corners 4 int Otsu(IplImage* src); i

[求助]OpenCV:識別四邊形問題,待解決

矩形原影象見最下面。 思路是,採用L1、L2、L3和L4四條線,按照如圖所示方向依次掃過圖形,遇到角點停止,返回座標。 (該方法只對部分規則的四邊形適用) 問題是A和B點的識別程式通不過,請問問大家是怎麼回事,該如何解決? 原始碼如下: // gangban.cpp

2012 不宜進入的三技術

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

2012 不宜進入的三技術

                執行緒執行緒是指程序中的一個單一順序的控制流,是作業系統能夠排程的最小單位,一個程序中可以有多條執行緒,分別執行不同的任務。執行緒有核心執行緒和使用者執行緒之分,但在本文中僅指核心執行緒。在軟體開發中,使用執行緒有以下好處:1、在多核或多路 CPU 的機器上多執行緒程式能夠併發

Unity之一天一技術---到包圍盒的最近

Rigidbody.ClosestPointOnBounds 到包圍盒的最近點public class example : MonoBehaviour { function Start () { var explosionPosition = transform.posi

Unity之一天一技術---旋轉問題

旋轉問題 unity3d中圍繞一個指定的點旋轉 gameobject.transform.RotateAround(pos:Vector3, rotateAngle:vector); 引數1是要圍繞的座標點,第二個引數是旋轉角度(x軸角度,y軸角度,z軸角度)  以自身座標

資料庫事務的基本性質ACID

資料庫事務概念 什麼是資料庫事務? 事務(transaction)是由指邏輯上對資料的的一組操作, 這組操作要麼一次全部成功,如果這組操作全部失敗,是不可分割的一個工作單位。 資料庫事務的四個基本性質(ACID) 1. 原子性(Atomicity) 事務的原子性

Unity之一天一技術---解決U3D程式“按下休眠鍵時退出程式”的問題

解決U3D程式“按下休眠鍵時退出程式”的問題(官方解決方案)   更改AndroidManifest.xml中的<activity>標籤,來包含<android:configChanges>標記 活動標籤示例如下所示:- <activity a

python例項:解決經典撲克牌遊戲 -- 張牌湊24

  Hey! 如果你還沒有看這篇的上文的話,可以去稍稍瞅一眼,會幫助加速理解這一篇裡面涉及到的遞迴結構哦!(上一篇點這裡:《python例項:解決經典撲克牌遊戲 -- 四張牌湊24點 (一)》)   如果你已經看完了第一部分的解析,那我們可以來繼續上道題的第二部分。   根據第一部分的分析,第二部分的難點主要

opencv中的SVM圖像分類

proc 文本 c_str lec 源碼 open right tle 特征描述 opencv中的SVM圖像分類(二) 標簽: svm圖像 2015-07-30 08:45 8296人閱讀 評論(35) 收藏 舉報 分類: 【opencv應用】(5) 版

Java2實用教程第5版重要點及遺漏

變量 每一個 實現接口 變量名 等於 優勢 2層 4.3 管理 3.2 語句概述 一個分好也是一條語句,稱作空語句。 3.3.1 if語句 If(表達式) If後面的一堆小括號()內的表達式的值必須是boolean類型 3.3.2 if-else語句 If-else

Windows核心編程之核心總結章 進程2018.6.17)

函數的參數 設置 函數詳解 可執行文件 一次 HA AC 關聯 原型 學習目標 上一節我們了解了進程、入口函數和進程實例句柄等內容,在進入進程的命令行學習前,有一個全局變量初始化問題需要測試一波。本節的學習目標如下:1.測試C/C++運行庫啟動函數初始化哪些全局變量2.進程

Spring Cloud--鴻鵠Cloud分布式微服務雲系統—技術

oop osql oot api 可能 stream dock dfs base 鴻鵠Cloud是基於springcloud的,spring cloud本身提供的組件就很多,但我們需要按照企業的業務模式來定制企業所需要的通用架構,那我們現在需要考慮使用哪些技術呢? 下面我針

Pthon學習之路 第篇 Python基礎

pri bsp programs -s alt 如果 lex class 算數運算 1.運算符:+ - *(乘法) /(除法) %(求余) //(求商) **(求冪) 2.成員運算:in not in:判斷單個字符或者子序列在不在字符串中。(n

《C++ Primer Plus》學習筆記——第章 複合型別

結構 結構是一種比陣列更靈活的資料格式,因為同一個結構可以儲存多種型別的資料。 結構是OOP堡壘(類)的基石。 結構是使用者定義的結構,而結構宣告定義了這種型別的資料屬性。定義結構描述——他描述並標記了能夠儲存在結構中的各種資料型別。然後按描述建立結構變數。 使用結構體必須先結構宣告

在蘇州微軟的三月實習

上一篇 主要說了下我的mentor 。 這一篇把我的實習過程再具體一些,以及我和在同一個會議室的最終在微軟工作的另一個實習生的互動(叫他Fox吧,就是前面和我交換任務的人。)另,我們的會議室是四個人共享的。另外兩個人叫他們 Hippo 和 Snake吧,其中Snake 是女生。如果你想最

python基礎注意

 每個模組都有一個__name__屬性,當其值是'__main__'時,表明該模組自身在執行,否則是被引入。 說明:__name__ 與 __main__ 底下是雙下劃線, _ _ 是這樣去掉中間的那個空格。 內建的函式 dir()

java B2B2C 原始碼 多級分銷Springcloud多租戶電子商城系統- 整合企業架構的技術

spring cloud本身提供的元件就很多,但我們需要按照企業的業務模式來定製企業所需要的通用架構,那我們現在需要考慮使用哪些技術呢? 下面我針對於spring cloud微服務分散式雲架構做了以下技術總結,希望可以幫助到大家: View: H5、Vue.js、Spring Tag、React

章 儲存器管理

4.5 分頁儲存管理方式 1.連續分配方式:一個程序連續的裝進記憶體一個大小合適的區。->“碎片”->“緊湊”->增大開銷 2.如果允許一個程序直接分散裝入多個不相鄰分割槽中,則無需“緊湊”->產生儲存管理的離散分配方式。 3.離散分配三種方式:

總結Spring框架擴充套件bean生命週期中的擴充套件持續更新中...

面向業務開發的時候,程式設計師需要明白業務的邏輯,並設計程式碼結構。而在進行中介軟體開發的時候,則需要明白框架的邏輯,進行開發。 所以要開發提供給spring的中介軟體,需要知道spring中有哪些擴充套件點,好在對應的地方插入我們的功能。 1. Spring容器初始化b