【OpenCV影象處理】二十二、影象邊緣檢測(上)
→影象邊緣檢測的目的是檢測鄰域內灰度明顯變化的畫素,常用一階差分和二階差分來進行邊緣檢測
→數字影象中的邊緣是由鄰域內灰度值明顯變化的畫素構成,邊緣檢測主要是影象灰度的度量檢測和定位
→影象的邊緣有方向和幅值兩個屬性,沿邊緣方向畫素灰度值變化平緩或不發生變化,而垂直於邊緣方向畫素灰度值變化劇烈
→需要理解的是,邊緣是灰度值變化的產物,可以利用差分來檢測這種不連續性,邊緣檢測方法大致可以分為兩類:
(1)基於一階差分的方法
(2)基於二階差分的方法
→一階差分運算元通過尋找一階差分中的最大值來檢測邊緣,將邊緣定位在一階差分最大的方向
→二階差分運算元通過尋找二階差分過零點來定位邊緣,常用的有Laplace過零點等
在實際影象中,影象的邊緣部分通常具有一定的斜坡面,斜坡部分與邊緣模糊程度成比例
→邊緣的寬度取決於其是灰度值到終止灰度值的斜面長度,而斜面長度取決於模糊程度
灰度不連續檢測(間斷檢測)是最普遍的邊緣檢測方法:
在邊緣檢測中,梯度運算元是常用的一階差分運算元,用於檢測影象中邊緣的存在和強度,Laplace運算元是常用的二階差分運算元,二階差分在邊緣亮的一邊符號為負,在邊緣暗的一邊符號為正。而在邊緣處,二階差分穿過零點
應該注意的是,差分操作對噪聲十分敏感
→對於有噪邊緣,利用差分檢測影象邊緣將放大噪聲的影響,因此在利用差分進行邊緣檢測時,應該謹慎的考慮噪聲的影響,通常在進行邊緣檢測之前對影象進行去噪或降噪處理
→利用一階差分模板檢測影象邊緣實際上是利用一種區域性處理的方法,當某一畫素鄰域內的灰度值的一階差分大於閾設值時,則判定該畫素為邊緣畫素。
→利用一階差分模板提取的邊緣影象是由許多不連續的邊緣組成,這些邊緣畫素勾畫出各個物體的輪廓,但是不能形成影象分割所需的閉合且連通的邊界。
邊緣連線:
是指將鄰近的邊緣畫素連線起來,從而產生一條閉合且連通邊緣的過程。根據事先定義的連結準則,對這樣的邊緣畫素進行邊緣連線處理,天不由於噪聲和陰影造成的間斷。
→利用二階差分模板檢測影象邊緣實際上是尋找二階差分過零點,二階差分模板產生連續的邊緣,但是不能保證檢測的邊緣是準確的,只能檢測邊緣的大致形狀。
下面首先介紹一階差分運算元,大致可以分為兩類,分別是梯度運算元
(1)梯度運算元
梯度運算元定義在二維一階導數的基礎上,在數字影象中,由於畫素是離散的,因此常用差分來近似偏導數
→對於一幅數字影象f(x,y),在畫素(x,y)處梯度定義為:
向量
其中,Gx(x, y)和Gy(x, y)分別表示x(垂直)和y(水平)方向上的一階差分
在邊緣檢測中,一個重要的量是梯度的幅度,用公式可以表示為
上式中,mag{·}表示求幅度的函式,但是為了降低複雜度,避免進行平方和開放運算,所以求幅度的公式通常寫為如下形式:
使用上面這種絕對和計算簡單而且保持了灰度的相對變化
→但是,也導致了梯度運算元不具備各向同性→也就是不具備旋轉不變性,梯度的方向指向畫素值f(x, y)在(x,y)處增加最快的方向。
梯度關於x軸的角度為:
上式表示的是畫素(x,y)處梯度關於x軸的方向角,這一點的梯度方向和該點邊緣方向垂直
→梯度運算元檢測灰度值變化的兩個屬性是灰度值的變化率和方向,分別用幅度和方向來表示
→梯度的計算需要在每一個畫素位置計算兩個方向的一階差分,常用的一階差分運算元有Robberts,Prewitt和Sobel運算元等
在介紹各個運算元之前,先給出一個3x3畫素領域的定義,如下圖所示:
首先簡單介紹一下Robberts交叉運算元,這是最簡單的梯度運算元,
在中心畫素x(垂直)方向上,一階差分計算式為
Gx = z9 - z5
在中心畫素y(水平)方向上,一階差分計算式為
Gy = z8 - z6
需要說明的是,Robbert交叉運算元沒有固定的中心點,因此不能使用2x2的模板卷積來實現
對於原始影象f(x,y),Roberts邊緣檢測輸出影象為g(x,y),影象的Roberts邊緣檢測可以用下式來表示:
具體實現程式如下所示:
//實現Roberts邊緣檢測
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace std;
//函式:Roberts運算元實現
Mat Roberts(Mat srcImage);
int main()
{
Mat srcImage = imread("2345.jpg",0);
if (!srcImage.data)
{
cout << "讀入圖片錯誤!" << endl;
system("pause");
return -1;
}
imshow("原影象", srcImage);
Mat dstImage = Roberts(srcImage);
imshow("Roberts邊緣檢測影象", dstImage);
waitKey();
return 0;
}
//函式:Roberts運算元實現
Mat Roberts(Mat srcImage)
{
Mat dstImage = srcImage.clone();
int rowsNum = srcImage.rows;
int colsNum = srcImage.cols;
for (int i = 0; i < rowsNum - 1; i++)
{
for (int j = 0; j < colsNum - 1; j++)
{
//根據公式進行計算
int t1 = (srcImage.at<uchar>(i, j) -
srcImage.at<uchar>(i + 1, j + 1))*
(srcImage.at<uchar>(i, j) -
srcImage.at<uchar>(i + 1, j + 1));
int t2 = (srcImage.at<uchar>(i + 1, j) -
srcImage.at<uchar>(i, j + 1))*
(srcImage.at<uchar>(i + 1, j) -
srcImage.at<uchar>(i, j + 1));
//計算對角線畫素差
dstImage.at<uchar>(i, j) = (uchar)sqrt(t1 + t2);
}
}
return dstImage;
}
程式執行後的結果如下所示:
→在實際使用中,常常使用Prewitt運算元和Sobel運算元來當做梯度運算元。
下面首先介紹利用影象差分運算進行邊緣檢測,然後再分別介紹各種邊緣檢測運算元,包括一階運算元和二階運算元
(1)影象差分運算:
對於原函式f(u),積分運算使計算f(u)對映到 f(u+a) - f(u+b)的值,差分運算分為前向差分和後向差分,一階前向差分是指Δf = f(u+1) - f(u),一階逆向差分是指Δf = f(u) - f(u-1)
二維離散影象f(x,y)在x方向的一階差分定義為Δfx = f(x+1, y) - f(x, y),y方向的一階差分定義為Δfy = f(x, y+1) - f(x, y)
差分運算通過求影象灰度變化劇烈處的一階微分運算元的極值來檢測奇異點,通過奇異點的值進一步設定閾值就可以得到邊緣二值化影象。
差分邊緣檢測中差分的水平或垂直方向都與邊緣方向正交,因此在實際應用場景中,常常將邊緣檢測分為水平邊緣,垂直邊緣和對角線邊緣,差分邊緣檢測定義方向模板如下所示:
垂直邊緣水平邊緣 對角線邊緣
利用OpenCV實現差分邊緣檢測例項如下所示:
//實現差分邊緣檢測
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace std;
//影象差分函式
void diffOperation(const Mat srcImage, Mat &edgeXImage, Mat &edgeYImage);
int main()
{
Mat srcImage = imread("2345.jpg", 0);
if (!srcImage.data)
{
cout << "讀入圖片錯誤!" << endl;
system("pause");
return -1;
}
imshow("原影象", srcImage);
Mat edgeXImage(srcImage.size(), srcImage.type());
Mat edgeYImage(srcImage.size(), srcImage.type());
//計算差分影象
diffOperation(srcImage, edgeXImage, edgeYImage);
imshow("垂直方向差分影象", edgeXImage);
imshow("水平方向差分影象", edgeYImage);
Mat edgeImage(srcImage.size(), srcImage.type());
//將水平與垂直邊緣進行疊加
addWeighted(edgeXImage, 0.5, edgeYImage, 0.5, 0.0, edgeImage);
imshow("水平和垂直方向邊緣", edgeImage);
waitKey();
return 0;
}
void diffOperation(const Mat srcImage, Mat &edgeXImage, Mat &edgeYImage)
{
Mat tempImage = srcImage.clone();
int rowsNum = tempImage.rows;
int colsNum = tempImage.cols;
for (int i = 0; i < rowsNum - 1; i++)
{
for (int j = 0; j < colsNum - 1; j++)
{
//計算垂直邊緣
edgeXImage.at<uchar>(i, j) =
abs(tempImage.at<uchar>(i + 1, j) - tempImage.at<uchar>(i, j));
//計算水平邊緣
edgeYImage.at<uchar>(i, j) =
abs(tempImage.at<uchar>(i, j + 1) - tempImage.at<uchar>(i, j));
}
}
}
執行程式後,效果如下圖所示:
(2)非極大值抑制
在介紹其餘的邊緣檢測運算元之前,首先簡單介紹一下影象中的非極大值抑制。
影象梯度矩陣中的元素值越大,說明影象中該點的梯度值越大,但是這並不能將它判斷為該點處的邊緣。
非極大值抑制操作可以提出為偽邊緣資訊,被廣泛應用於影象邊緣檢測中,其原理是通過畫素鄰域的區域性最優值,將非極大值點所對應的灰度值設定為背景畫素點,如畫素鄰域區域滿足梯度值區域性最優值則判斷為該畫素的邊緣,對其餘非極大值的相關資訊進行抑制,利用這個準則可以剔除大部分非邊緣點。
(3)Sobel邊緣檢測運算元
Sobel運算元是應用廣泛的離散微分運算元之一,常常用於影象處理中的邊緣檢測,計算影象灰度函式的近似梯度。利用影象畫素點Sobel運算元計算出相應的地圖向量及向量的範數,基於影象卷積來實現在水平方向與垂直方向檢測對應方向的邊緣。對於原影象與奇數Sobel水平核Gx,垂直核Gy進行卷積可計算水平與垂直變換,當核心大小為3x3時,Gx與Gy為下式:
對影象中沒一點結合卷積後的結果求出近似梯度幅度G:
G= √(Gx^2 + Gy^2)
Sobel運算元在進行邊緣檢測時效率較高,當對精度要求不是很高時,是一種比較常用的邊緣檢測方法。Sobel運算元對於沿著x軸和y軸的排列的邊緣表示的較好,但是對與其他角度的表示取不夠精確,這時候可以使用Scharr濾波器。這種濾波器的水平與垂直的核因子如下:
首先給出使用OpenCV中的自帶函式庫實現Sobel邊緣檢測,
在OpenCV中實現相關功能使用函式Sobel(),函式的宣告和說明如下所示:
void Sobel( InputArray src, OutputArray dst, int ddepth,int dx, int dy, int ksize=3,
double scale=1, double delta=0, int borderType=BORDER_DEFAULT );
第一個和第二個引數分別為源影象和輸出影象
第三個引數為int型別的ddepth,為輸出影象的深度,支援src.depth()和ddepth的組合:
(·若src.depth() = CV_8U,則取ddepth = -1 / CV_16S / CV_32F / CV_64F
(·若src.depth() = CV_16U / CV_16S ,則ddepth = -1 /CV_32F / CV_64F
(·若src.depth() = CV_32F,取ddepth = -1 /CV_32F / CV_64F
(·若src.depth() = CV_64F,取ddepth = -1 / CV_64F
第四個引數為int型別的dx,為x方向上的差分階數
第五個引數為int型別的dy,為y方向上的差分階數
第六個引數為int型別的ksize,有預設值3,表示Sobel核的大小,需要注意的是,Sobel運算元的核心大小必須取 1,3,5,7。
第七個引數是double型別的scale,計算導數值是可選的縮放因子,預設值為1,表示預設的情況下不進行放縮操作。可以查閱getDeriveKernels檢視相關內容
第八個引數是double型別的delta,表示在結果存入目標圖(dst)之前可選的delta值,有預設值0
第九個引數是int型別的bordertype,有預設值BORDER_DEFAULT,在之前的文章中有過這個引數的相關介紹,在這裡不再贅述。
具體程式如下:
//使用OpenCV自帶函式實現Sobel邊緣檢測
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage = imread("2345.jpg");
if (!srcImage.data)
{
cout << "讀入圖片錯誤!" << endl;
system("pause");
return -1;
}
Mat srcGray;
cvtColor(srcImage, srcGray, CV_BGR2GRAY);
imshow("原影象灰度圖", srcGray);
//定義邊緣圖,水平和垂直
Mat edgeImage, edgeImageX, edgeImageY;
//求x方向Sobel邊緣
Sobel(srcGray, edgeImageX, CV_16S, 1, 0, 3, 1, 0);
//求y方向的Sobel運算元
Sobel(srcGray, edgeImageY, CV_16S, 0, 1, 3, 1);
//線性變換,轉換輸入陣列元素為8位無符號整型
convertScaleAbs(edgeImageX, edgeImageX);
convertScaleAbs(edgeImageY, edgeImageY);
//x與y方向進行疊加
addWeighted(edgeImageX, 0.5, edgeImageY, 0.5, 0, edgeImage);
imshow("Sobel邊緣影象", edgeImage);
//定義scharr邊緣影象
Mat edgeXImageS, edgeYImageS, edgeImageS;
//計算X方向的Scharr邊緣
Scharr(srcGray, edgeXImageS, CV_16S, 1, 0, 1, 0);
convertScaleAbs(edgeXImageS, edgeXImageS);
//計算Y方向的Scharr邊緣
Scharr(srcGray, edgeYImageS, CV_16S, 0, 1, 1, 0);
convertScaleAbs(edgeYImageS, edgeYImageS);
//x與y方向進行邊緣疊加
addWeighted(edgeXImageS, 0.5, edgeYImageS, 0.5,0,edgeImageS);
imshow("Scharr邊緣影象", edgeImageS);
waitKey();
return 0;
}
執行後的結果如下所示:
可以看出,Scharr能夠保持更多更好的影象邊緣部分。
下面介紹不使用OpenCV中的函式庫實現Sobel邊緣檢測
(a.非極大值抑制Sobel邊緣檢測
→非極大值抑制Sobel邊緣檢測實現步驟主要如下:
(①.將影象轉換為32位浮點型資料,定義水平或垂直方向的Sobel運算元
(②.利用filter2D完成影象與運算元的卷積操作,計算卷積結果的梯度幅值
(③.自適應計算出梯度幅度閾值,閾值設定不大於梯度幅值的均值乘以4,根據與之對水平或垂直的鄰域區域梯度進行比較。
(④.判斷當前鄰域梯度是否大於水平或垂直鄰域梯度,自適應完成邊緣檢測處二值影象的操作。
對上面這個過程進行程式實現如下所示:
//影象非極大值抑制實現Sobel豎直細化邊緣
bool SobelVerEdge(Mat srcImage, Mat &dstImage)
{
CV_Assert(srcImage.channels() == 1);
srcImage.convertTo(srcImage, CV_32FC1);
//水平方向的Sobel運算元
Mat sobelX = (Mat_<float>(3, 3) << -0.125, 0, 0.125,
-0.25, 0, 0.25,
-0.125, 0, 0.125);
Mat ConResMat;
//卷積運算
filter2D(srcImage, ConResMat, srcImage.type(), sobelX);
//計算梯度的幅度
Mat gradMagMat;
multiply(ConResMat, ConResMat, gradMagMat);
//根據梯度幅度及引數設定閾值
int scaleVal = 4;
double thresh = scaleVal*mean(gradMagMat).val[0];
Mat resultTempMat = Mat::zeros(gradMagMat.size(), gradMagMat.type());
float *pDataMag = (float*)gradMagMat.data;
float *pDataRes = (float*)resultTempMat.data;
const int rowsNum = ConResMat.rows;
const int colsNum = ConResMat.cols;
for (int i = 1; i != rowsNum - 1; ++i)
{
for (int j = 1; j != colsNum - 1; ++j)
{
//計算這一點的梯度與水平或垂直梯度值的大小並比較結果
bool b1 = (pDataMag[i*colsNum + j] > pDataMag[i*colsNum + j - 1]);
bool b2 = (pDataMag[i*colsNum + j] > pDataMag[i*colsNum + j + 1]);
bool b3 = (pDataMag[i*colsNum + j] > pDataMag[(i - 1)*colsNum + j]);
bool b4 = (pDataMag[i*colsNum + j] > pDataMag[(i + 1)*colsNum + j]);
//判斷鄰域梯度是否滿足大於水平或垂直梯度的條件
//並根據自適應閾值引數進行二值化
pDataRes[i*colsNum + j] = 255 * ((pDataMag[i*colsNum + j] > thresh)
&& ((b1 && b2) || (b3 && b4)));
}
}
resultTempMat.convertTo(resultTempMat, CV_8UC1);
dstImage = resultTempMat.clone();
return true;
}
(b.影象直接卷積實現Sobel
影象直接卷積Sobel邊緣檢測實現比較簡單,首先定義水平或垂直方向的Sobel核因子,直接對源影象進行窗遍歷,計算視窗內的鄰域梯度幅值;然後根據梯度模長進行二值化操作,完成影象水平或垂直方向的邊緣檢測
影象直接卷積Sobel邊緣實現程式碼如下所示:
//影象直接卷積實現Sobel
bool SobelEdge(const Mat &srcImage, Mat &dstImage, uchar threshold)
{
CV_Assert(srcImage.channels() == 1);
//初始化水平核因子
Mat sobelX = (Mat_<double>(3, 3) << 1, 0, -1,
2, 0, -2,
1, 0, -1);
//初始化垂直核因子
Mat sobelY = (Mat_<double>(3, 3) << 1, 2, 1,
0, 0, 0,
-1, -2, -1);
dstImage = Mat::zeros(srcImage.rows - 2, srcImage.cols - 2, srcImage.type());
double edgeX = 0;
double edgeY = 0;
double graMag = 0;
for (int k = 1; k < srcImage.rows - 1; ++k)
{
for (int n = 1; n < srcImage.cols - 1; ++n)
{
edgeX = 0;
edgeY = 0;
//遍歷計算水平與垂直梯度
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
edgeX += srcImage.at<uchar>(k + i, n + j)*
sobelX.at<double>(1 + i, 1 + j);
edgeY += srcImage.at<uchar>(k + i, n + j)*
sobelY.at<double>(1 + i, 1 + j);
}
}
//計算梯度模長
graMag = sqrt(pow(edgeY, 2) + pow(edgeX, 2));
//進行二值化
dstImage.at<uchar>(k - 1, n - 1) =
((graMag > threshold) ? 255 : 0);
}
}
return true;
}
(c.影象卷積下非極大值抑制Sobel
影象卷積下非極大值抑制Sobel邊緣檢測的實現過程與之前的a部分比較類似。但是需要說明的是,非極大值抑制雖然能夠較好的剔除虛假邊緣點,但是對於某些特定場景下的邊緣檢測並不起作用,例如無損文字字元識別
相關的實現程式碼如下所示:
//影象卷積實現Sobel非極大值抑制
bool sobelOptaEdge(const Mat &srcImage, Mat &dstImage, int flag)
{
CV_Assert(srcImage.channels() == 1);
//初始化Sobel水平核因子
Mat sobelX = (Mat_<double>(3, 3) << 1, 0, -1,
2, 0, -2,
1, 0, -1);
//初始化Sobel垂直核因子
Mat sobelY = (Mat_<double>(3, 3) << 1, 2, 1,
0, 0, 0,
-1, -2, -1);
//計算水平與垂直卷積
Mat edgeX, edgeY;
filter2D(srcImage, edgeX, CV_32F, sobelX);
filter2D(srcImage, edgeY, CV_32F, sobelY);
//根據傳入的引數確定計算水平或垂直方向的邊緣
int paraX = 0;
int paraY = 0;
switch (flag)
{
case 0:
paraX = 1;
paraY = 0;
break;
case 1:
paraX = 0;
paraY = 1;
break;
case 2:
paraX = 1;
paraY = 1;
break;
default:
break;
}
edgeX = abs(edgeX);
edgeY = abs(edgeY);
Mat graMagMat = paraX*edgeX.mul(edgeX) +
paraY*edgeY.mul(edgeY);
//計算閾值
int scaleVal = 4;
double thresh = scaleVal*mean(graMagMat).val[0];
dstImage = Mat::zeros(srcImage.size(), srcImage.type());
for (int i = 1; i < srcImage.rows - 1; i++)
{
float *pDataEdgeX = edgeX.ptr<float>(i);
float *pDataEdgeY = edgeY.ptr<float>(i);
float *pDataGraMag = graMagMat.ptr<float>(i);
//閾值化和極大值抑制
for (int j = 1; j < srcImage.cols - 1; j++)
{
//判斷當前鄰域梯度是否大於閾值與大於水平或垂直梯度
if (pDataGraMag[j]>thresh &&
(pDataEdgeX[j]>paraX*pDataEdgeY[j] &&
pDataGraMag[j] > pDataGraMag[j - 1] &&
pDataGraMag[j] > pDataGraMag[j + 1] ||
(pDataEdgeY[j] > paraY*pDataEdgeX[j] &&
pDataGraMag[j] > pDataGraMag[j - 1] &&
pDataGraMag[j] > pDataGraMag[j + 1])))
dstImage.at<uchar> = 255;
}
}
return true;
}
相關推薦
【OpenCV影象處理】二十二、影象邊緣檢測(上)
→影象邊緣檢測的目的是檢測鄰域內灰度明顯變化的畫素,常用一階差分和二階差分來進行邊緣檢測 →數字影象中的邊緣是由鄰域內灰度值明顯變化的畫素構成,邊緣檢測主要是影象灰度的度量檢測和定位 →影象的邊緣有方向和幅值兩個屬性,沿邊緣方向畫素灰度值變化平緩或不發生變化,而垂直於邊緣方
【OpenCV學習筆記】三十七、特徵檢測與匹配(二)——SIFT特徵點匹配
特徵檢測與匹配(二)——SIFT特徵點匹配 1.SIFT特徵點提取 2.繪製特徵點 3.特徵點描述符(特徵向量)提取 4.使用暴力匹配器進行暴力匹配 5.對匹配結果進行篩選(依據DMatch結構體中的float型別變數distance進行篩選) 6.繪製匹配結果 先上ppt
【數字影象處理】pbm/pgm/ppm圖片的讀寫(Matlab)
Ø 【作業要求】 1. Get your matlab platform ready. Payspecial attention to the image processing toolbox.
二十六、COUNT(*)與COUNT(列)到底誰更快?
COUNT(*)與COUNT(列)到底誰更快? *count(列)當列值為空,將不被統計。 1、資料準備 以下命令執行有問題請參照上篇文章 --做個試驗,看看到底誰更快? dr
【網站架構學習】萬無一失:網站的高可用架構(上)
一、網站的高可用架構 2011年4月12曰,亞馬遜計算服務EC2 ( Elastic Computer Cloud )發生故障,其 ESB( Elastic Block Storage)服務不可用,故障持續了數天,最終還是有部分資料未能恢復。這一故
第十章、日常運維(上)
抓取 進入 fff 0.11 cpu rip 筆記 裏來 ifd 10.1 使用w查看系統負載 10.2 vmstat命令 10.3 top命令 10.4 sar命令 10.5 nload命令 10.6 監控io性能 10.7 free命令 10.8 ps命令 10.9 查
【OpenCV影象處理】二十五、角點檢測
部落格參考 朱偉 等編著的《OpenCV影象處理程式設計例項》 ====================================================================================== 在很多應用場景中,影象畫素區域的興趣
【OpenCV影象處理】二十三、影象邊緣檢測(下)
(1)Prewitt邊緣檢測運算元 →prewitt邊緣檢測運算元是另一種常用的一階邊緣檢測運算元,這個運算元對於噪聲有抑制的作用。 Prewittt邊緣檢測的原理和Sobel邊緣檢測類似,都是在影象空間利用兩個方向模板與影象進行鄰域卷積來完成的,分別對水平和垂直方向邊緣進
【OpenCV影象處理】十九、數學形態學方法(中)
1.擊中擊不中運算 擊中擊不中(hit or miss)定義在交集為空集的兩個結構元素的膨脹和腐蝕運算的基礎上。設B =(B1,B2)表示結構元素對,且B1 ∩ B2 = ∅ 則結構元素B對集合A的擊中積補種運算,記做 定義為: →運算過程為: (→當且僅當B1平移某一
【第四組】第十二次沖刺會議報告
commit 執行 完成 技術文檔 整體 alt 點擊 轉換 導入 張:做了:美化初始化界面,解決文件沖突 困難:嵌入js的時候傳的是string[],但是只執行string[0] 規劃:多個點的連接(動態添加point),點擊標簽跳轉,導入圖片,顯示界面 孔:做了:細
【Unity3D Shader程式設計】之十二 可程式設計Shader初步 & 漫反射可程式設計Shader的實現
毛星雲,網路ID「淺墨」,90後,熱愛遊戲開發、遊戲引擎、計算機圖形、實時渲染等技術,就職於騰訊互娛。 微軟最有價值專家 著作《Windows遊戲程式設計之從零開始》、《OpenCV3程式設計入門》 碩士就讀於南京航空航天大學航天學院(2013級碩士研究生),已於2016年三月畢業。本科
【影象處理】MATLAB:點、線、邊緣檢測
點檢測 程式碼示例 f = imread('test_pattern_with_single_pixel.tif'); w = [-1 -1 -1;-1 8 -1;-1 -1 -1];
【OpenCV學習筆記】三十、輪廓特徵屬性及應用(七)—位置關係及輪廓匹配
輪廓特徵屬性及應用(七)—位置關係及輪廓匹配 1.計算點與輪廓的距離及位置關係——pointPolygonTest() 2.矩的計算——moments() 3.形狀匹配(比較兩個形狀或輪廓間的相似度)
【影象處理】一種低光照影象的亮度提升方法(Adaptive Local Tone Mapping Based on Retinex for High Dynamic Range Images)
前言 在實際的拍照過程中,常常會遇到,光線不足的情況。這時候單反使用者一般會調大感光度,調大光圈,以讓照片整體更清晰,更亮。那麼如果照片已經被拍的很暗了,怎麼辦呢?這時候我們可以利用演算法來提升影象整體的光照情況,讓影象更清晰。 2013年這篇《Ada
【數字影象處理】灰度直方圖、直方圖均衡化、直方圖規定化
灰度直方圖 一幅影象由不同灰度值的畫素組成,影象中灰度的分佈情況是該影象的一個重要特徵。影象的灰度直方圖就描述了影象中灰度分佈情況,能夠很直觀的展示出影象中各個灰度級所佔的多少。影象的灰度直方圖是灰度級的函式,描述的是影象中具有該灰度級的畫素的個數:其中,橫座標是灰度級,
二十六、正則介紹grep上、grep中、grep下
grep egrep 二十六、正則介紹grep上、grep中、grep下正則介紹grep正則:一串有規律的字符串。它使用單個字符串來描述或匹配一系列符合某個句法規則的字符串。很多文本編輯器或其他工具裏,正則表達式通常用來檢索和替換那些符合某個模式的文本內容。許多程序設計語言也都支持利用正則表達式進行字
二十五、SpringBoot與分散式(Zookeeper和Dubbo、Spring Boot和Spring Cloud)
一、分散式應用 在分散式系統中,國內常用zookeeper+dubbo組合,而SpringBoot推薦使用全棧的Spring,SpringBoot+SpringCloud。 分散式系統: 單一應用架構 當網站流量很小時,只需一個應用,將所有功能都部署在一起,以減
【C/C++學習】之十四、RTTI
RTTI(Runtime TypeIdentification) 提供了執行時確定物件型別及轉換指標或引用型別的方法。 有關內容包括類名稱,資料成員名稱與型別,函式名與型別等。 在大多數面向度地向專
【黑金原創教程】【FPGA那些事兒-驅動篇I 】實驗十五:FIFO儲存模組(同步)
實驗十五:FIFO儲存模組(同步) 筆者雖然在實驗十四曾解釋儲存模組,而且也演示奇怪的傢伙,但是實驗十四隻是一場遊戲而已。至於實驗十五,筆者會稍微嚴肅一點,手動建立有規格的儲存模組,即同步FIFO。那些看過《時序篇》的同學一定對同步FIFO不會覺得陌生吧?因為筆者曾在《時序篇》建立基於移位暫存器的同步FIF
Androin學習筆記四十二:Java android Socket通訊檢測(server)連線是否斷開
Pre 在利用socket寫通訊程式的時候,想檢測伺服器是否還活著。 從網上找了很多資料,都沒有自己合適的,最後自己想了個辦法,不過也相當於截取了心跳檢測的一部分。 這裡檢測的是遠端server的連線,而不是本地是否連線成功。首先想到socket類的方法isClosed()、isConnected