エッジ処理
畳み込み問題エッジ
境界画素はそうエッジ処理されていないが存在するフィルタ3X3画素は、濾過カーネルと完全にオーバーラップされないので、画像境界画素は畳み込みは、畳み込み演算ができない場合、5X5がある場合2つのエッジ画素が処理されていません。
エッジ処理
このような画素のエッジの周りの3×3パディング、したがって画像のエッジを処理することを保証し、次にコンボリューション処理後にそれらを除去するよう畳み込み開始エッジ画素、画素値0または充填黒RGB、前増加エッジ、OpenCVのデフォルトのアプローチがある:BORDER_DEFAULT、他にいくつかある一般的に使用される他の
BORDER_CONSTANT ---指定されたエッジピクセル値で充填された
エッジ画素の既知の値を用いてエッジ画素を充填--- BORDER_REPLICATE
BORDER_WRAP ---とピクセル充填を補償するための他の側
APIは、画像のエッジ説明---のAPIに追加され
copyMakeBorder(
マットSRC、//入力画像
マットDST、//追加エッジ画像
INTトップ、//通常約上下同じ値にエッジ長、
int型の底、
intは左、
INT右、
INT borderType、//エッジ型
スカラー値
)
コードは示しています。
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("C:\\Users\\Lenovo\\Desktop\\毕业设计\\AAAAAAA\\1.jpg");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
char INPUT_WIN[] = "input image";
char OUTPUT_WIN[] = "Border image";
namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
namedWindow(OUTPUT_WIN,CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN, dst);
int top = (int)(0.05 * src.rows);
int left = (int)(0.05 * src.cols);
int right = (int)(0.05 * src.cols);
int bottom =(int)(0.05 * src.rows);
RNG rng(12345);
int borderType = BORDER_DEFAULT;
int c = 0;
while (true) {
c = waitKey(500);
if ((char)c == 27) {//ESC退出
break;
}
if ((char)c == 'r') {
borderType = BORDER_REPLICATE;
}
else if ((char)c == 'w') {
borderType = BORDER_WRAP;
}
else if ((char)c == 'c') {
borderType = BORDER_CONSTANT;
}
else {
borderType = BORDER_DEFAULT;
}
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
copyMakeBorder(src, dst, top, bottom, left, right, borderType, color);
imshow(OUTPUT_WIN, dst);
}
waitKey(0);
return 0;
}
ソーベルオペレータ
畳み込みアプリケーション---画像エッジ抽出
エッジは何-顕著なの一つであり、画素値の遷移が起こるされた画像特徴抽出において、画像の特徴、物体検出の態様は、Moshishibieなどが重要な役割有する
キャッチする方法を/ ---、その一次導関数を探しているエッジ画像抽出
デルタ= F(X)を- 、F (X-1)、デルタ大きく、x方向の変化、強いエッジ信号に大きい画素を示します。
ソーベル演算子は、
離散微分演算子(離散微分演算子)、画像強度の勾配を算出するための略である
Sobelオペレータ機能及び誘導体平滑微分ガウスのセット
、また1次微分演算子、誘導体オペレータとして知られていますで水平および垂直両方向誘導体、X方向の画像を取得し、Y方向勾配画像
Lapulasiオペレータは、二次微分演算子である
垂直勾配の水平勾配
のGx = -1 0 1グレイ= -1 -2 - 1
-2 0 2 0 0 0
-1 0 2 1 1 1
拡大するために重量差によると、
最終的な画像勾配
G =(Gxを*のGx + Gyの *グレイ) 平方根の
事実近似アルゴリズムが使用される:G = | Gxを| + | Gyの|
Sobelオペレータは、
逆数の近似値を取得し、カーネル= 3ときに、非常に正確ではありません、 Scharr関数の修正バージョンを使用して、オペレータは次のとおり
。-3 0 -3 -10 -3 3
のGx = Gyが= 10 -10 0 0 0 0
-3 0 3 3 10 3
APIは、ソーベル:: CVの説明
CV ::ソーベルを(
InputArray SRC、//入力画像
outputArrayのDST、//出力画像は、入力画像のサイズ一貫
INT深さ、//出力画像深度
int型DX、// X方向、いくつかの一次導関数
のint DY、// Y方向、いくつかの階微分
int型ksize、// Sobelオペレータのカーネルサイズは、である必要があります1,3,5,7-
ダブルスケール= 1、
ダブルデルタ= 0、
INT borderType = BORDER_DEFAULT
)
入力深さ()出力深さ(ddepth)
CV_8U -1 / CV_16S / CV_32F / CV_64F
CV_16U / CV_16S -1 / CV_32F / CV_64F
CV_32F -1 / CV_32F / CV_64F
CV_64F -1 / CV_64F
OpenCVのバージョンScharrを改善
APIはScharr :: CVの説明
CV :: Scharr(
InputArray SRC、//入力画像
OutputArrayのDST、//出力画像は、入力画像のサイズ一貫
INT深さ、//出力画像深度
、int型のDXを// X方向、いくつかの一次導関数
のint DY、// Y方向、いくつかの一次導関数
ダブルスケール= 1、
ダブルデルタ= 0、
INT borderType = BORDER_DEFAULT
)
短所:
ノイズに敏感な、脆弱
平滑化されたノイズ、ガウスぼかし、
グレースケール画像には、
xおよびy勾配必要な
混合のXY
振幅画像を
コードは示しています。
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
int main(int argc,char** argv){
Mat src,dst;
src = imread("");
if(!src.data){
printf("could not load image...\n");
return -1;
}
char INPUT_WIN[] = "Input image";
char OUTPUT_WIN[] = "Output image";
namedWindow(INPUT_WIN,CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN,src);
Mat gray_src;
GaussianBlur(src,dst,Size(3,3),0,0);
cvtColor(dst,gray_src,CV_BGR2GRAY);
imshow("gray image",gray_src);
Mat xgrad,ygrad;
//原始版本
//Sobel(gray_src,xgrad,CV_16S,1,0,3);
//Sobel(gray_src,ygrad,CV_16S,0,1,3);
//改进版本
Scharr(gray_src,xgrad,CV_16S,1,0);
Scharr(gray_src,ygrad,CV_16S,0,1);
convertScaleAbs(xgrad,xgrad);
convertScaleAbs(ygrad,ygrad);
imshow("xgrad image",xgrad);
imshow("ygrad image",ygrad);
//第一种算法
//Mat xygrad;
//addWeighted(xgrad,0.5,ygrad,0.5,0.xygrad);
//imshow("Final image",xygrad);
//第二种算法,效果更好
Mat xygrad = Mat(xgrad.size(),xgrad.type());
int width = xgrad.cols;
int height = xgrad.rows;
for(int row = 0; row < height; row++){
for(int col = 0; col < width; col++){
int xg = xgrad.at<uchar>(row,col);
int yg = ygrad.at<uchar>(row,col);
int xy = xg + yg;
xygrad.at<uchar>(row,col) = saturate_cast<uchar>(xy);
}
}
waitKey(0);
return 0;
}
Laplanceオペレータ
理論
説明:二次導関数、変化の最大値がゼロ、すなわちである場合、エッジはゼロです。この理論によれば、二次導関数によって計算さ、我々は画像、エッジ抽出の2階微分を計算することができます。
Laplanceオペレーター:
Laplance(F)= F(X)は、+ F(Y)の二次導関数は、の二次導関数であり
、関連するAPIのCV :: Laplance
プロセスフロー:
ガウスぼかし---ノイズには、(ガウスぼかし())
)(階調cvtColorに変換され、
二次導関数(ラプラシアン())を計算---ラプラス
)(絶対値converScaleAbsのに
結果を示します
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
int main(int argc,char** argv){
Mat src,dst;
src = imread();
if(!src.data){
printf("could not load image\n");
return -1;
}
namedWindow("input image",CV_WINDOW_AUTOSIZE);
imshow("input image",src);
Mat gray_src,edg_image;
GaussianBlur(src,dst,Size(3,3),0,0);
cvtColor(dst,gray_src,CV_BGR2GRAY);
Laplacian(gray_src,edg_image,CV_16S,3);
convertScaleAbs(edg_image,edg_image);
//图像二值化
threshold(edg_image,edg_image,0,255,THRESH_OTSU|THRESH_BINARY);
namedWindow("output image",CV_WINDOW_AUTOSIZE);
imshow("output image",edg_image);
waitKey(0);
return 0;
}
キャニーエッジ検出
キャニーアルゴリズムを説明
キャニーエッジ検出アルゴリズム、1986年に、
良好なエッジ抽出アルゴリズムがあり
、非常に一般的で非常に有用な画像処理方法の
ステップ:CV ::キャニー
ガウスぼかし---ガウスぼかし
階調変換- --cvtColor
---ソーベル/ Scharr勾配を計算
非最大抑制信号
出力バイナリ画像の閾値のレベル
の非最大抑制信号:
。のGx =グレイ= 1 0 -1 -1 -1 -2
-2 0 0 2 0 0
-1 0 2. 1. 1 1
G * = GxとGyとのGx + Gyの*平方根
角=逆正接(のGx / Gyの)
請求項180に黄色22.5から0の範囲内の領域と157.5
67.5 22.5の範囲でグリーンゾーン
112.5 -範囲67.5でブルー面積
157.5 - 112.5範囲で赤色領域
低閾値バイナリ画像出力
T1、T2は、閾値と、上記のすべては、T2、T1は、画素から落下人よりも小さい保持され、T1より大きいT2よりも高いが、すべての相互接続を保持します。最終的に二値画像出力を得ます
推奨される高及び低閾値比T2:T1 = 3; 1/2: 1 高閾値T2は、T1は、低閾値で
:: APIcvキャニー()
キャニー(
InputArray SRC、//「ビットの入力画像8-。
OutputArrayエッジ/通常、バイナリ画像は、背景が黒/出力エッジ画像であり、
しばしば1/2又は1/3の高しきい値で二重THRESHOLD1、//低しきい値、
ダブルthreshold2に、高閾値//
INT aptertureSize、// Sobelオペレータサイズは、典型的には3×3の範囲。3
BOOL選択L2gradient //真手段L2を正規化するために、またはL1によって正規化
)
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
Mat src,dst,gray_src;
int t1_value = 50;
int max_value = 255;
void Canny_Demo(int,void*);
int main(int argc,char** argv){
src = imread();
if(!src.data){
printf("could not load image\n");
return -1;
}
namedWindow("input image",CV_WINDOW_AUTOSIZE);
imshow("input image",src);
cvtColor(src,gray_src,CV_BGR2GRAY);
createTrackbar("Threshold Value","output image",&t1_value,max_value,Canny_Demo);
Canny_Demo(0,0);
waitKey(0);
return 0;
}
void Canny_Demo(int,void*){
Mat edge_output;
blur(gray_src,gray_src,Size(3,3),Point(-1,-1),BORDER_DEFAULT);
Canny(gray_src,edge_output,t1_value,t1_value * 2,3,false);
dst.create(src.size(),src.type());
src.copyTo(dst,edge_output);
imshow("output image",dst);
}