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