卷積邊界問題
圖像卷積時(shí)邊界像素不能被卷積計(jì)算進(jìn)去克饶,因?yàn)檫吔缣幭袼貨]有完全跟kernel重疊抬纸,當(dāng)ksize等于3時(shí),邊緣有1個(gè)像素沒有被處理弦悉,當(dāng)ksize等于5時(shí)窒典,邊緣有2個(gè)沒有被處理。
處理邊緣
??在卷積開始前增加邊緣像素稽莉,填充的像素為白色或黑色瀑志,這樣確保圖像的邊緣被處理,在卷積計(jì)算之后去掉這些邊緣肩祥,opencv默認(rèn)處理的方法是copyMakeBorder(src, dst, top, bottom, left, right, borderType, color)
??其中默認(rèn)的borderType是BORDER_DEFAULT后室,另外還有BORDER_WRAP缩膝,BORDER_CONSTANT混狠,BORDER_REPLICATE三種類型
- BORDER_WRAP 用另外一邊邊緣像素來填充
- BORDER_CONSTANT 用指定像素填充
- BORDER_REPLICATE 用已知的邊緣像素值填充
BORDER_REPLICATE .png
BORDER_WRAP .png
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
Mat src, dst;
int main(int argc, int ** argv)
{
src = imread("F:/cat.png");
if (!src.data) {
printf("無法加載圖片\n");
return -1;
}
namedWindow("input img", CV_WINDOW_AUTOSIZE);
namedWindow("output img", CV_WINDOW_AUTOSIZE);
imshow("input img", src);
int top = (int)(0.05*src.rows);
int bottom = (int)(0.05*src.rows);
int left = (int)(0.05*src.cols);
int right = (int)(0.05*src.cols);
RNG rng(12345);
int borderType = BORDER_DEFAULT;
int c = 0;
while (true) {
c = waitKey(500);
//ESC
if ((char)c == 27) {
break;
}
if ((char)c == 'r') {
borderType = BORDER_REPLICATE;
}
if ((char)c == 'c') {
borderType = BORDER_CONSTANT;
}
if ((char)c == 'w') {
borderType = BORDER_WRAP;
}
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("final result", dst);
}
waitKey(0);
return 0;
}
邊緣檢測
Canny算法是很好的邊緣檢測算法,算法分5步
- 高斯模糊
- 灰度轉(zhuǎn)換
- 梯度計(jì)算
- 非最大信號(hào)抑制
- 高低閾值輸出二值圖像
Canny(src, edge_output, low_threshold, h_threshold , ksize, L2gradient)
高低閾值輸出二值圖像
高低閾值分別為T2疾层,T1将饺,凡是高于T2的保留,低于T1的舍棄痛黎,從逃獄T2的出發(fā)予弧,凡是大于T1而且直接連接的都保留,最后得到二值圖像湖饱。
推薦T1和T2的關(guān)系是T2:T1 = 2:1或3:1
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
Mat src, dst, gray;
int g_value = 60;
int maxvalue = 255;
void cannry_callback(int, void *);
int main(int argc, int ** argv)
{
src = imread("F:/cat.png");
if (!src.data) {
printf("無法加載圖片\n");
return -1;
}
namedWindow("input img", CV_WINDOW_AUTOSIZE);
namedWindow("output img", CV_WINDOW_AUTOSIZE);
imshow("input img", src);
cvtColor(src, gray, CV_BGR2GRAY);
createTrackbar("threshold value:", "output img", &g_value, maxvalue, cannry_callback);
cannry_callback(0, 0);
waitKey(0);
return 0;
}
void cannry_callback(int, void *) {
Mat edge_output;
blur(gray, gray, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);
Canny(gray, edge_output, g_value, g_value * 2, 3, false);
imshow("output img", ~edge_output);
}
輸出結(jié)果演示
image.png