OpenCV中積分圖函數與應用
一:圖像積分圖概念
積分圖像是Crow在1984年首次提出,是為了在多尺度透視投影中提高渲染速度。隨后這種技術被應用到基于NCC的快速匹配、對象檢測和SURF變換中、基于統計學的快速濾波器等方面。積分圖像是一種在圖像中快速計算矩形區域和的方法,這種算法主要優點是一旦積分圖像首先被計算出來我們可以計算圖像中任意大小矩形區域的和而且是在常量時間內。這樣在圖像模糊、邊緣提取、對象檢測的時候極大降低計算量、提高計算速度。第一個應用積分圖像技術的應用是在Viola-Jones的對象檢測框架中出現。


上圖左側四個點的矩形區域像素求和,只要根據每個點左上方所有像素和表值,進行兩次減法與一次加法即可=》46 – 22 – 20 + 10 = 14
二:OpenCV中積分圖函數
OpenCV中通過integral()函數可以很容易的計算圖像的積分圖,該函數支持和表積分圖、平方和表積分圖、瓦塊和表積分圖計算。integral函數與參數解釋如下:
-
void cv::integral( -
InputArray src, // 輸入圖像 -
OutputArray sum, // 和表 -
OutputArray sqsum, // 平方和表 -
int sdepth = -1, // 和表數據深度常見CV_32S -
int sqdepth = -1 // 平方和表數據深度 常見 CV_32F -
)
三:使用積分圖函數
通過代碼演示計算積分圖實現任意窗口大小的盒子模糊與垂直邊緣提取,完整的代碼實現如下:
-
#include -
#include -
-
using namespace cv; -
using namespace std; -
-
void blur_demo(Mat &image, Mat &sum); -
void edge_demo(Mat &image, Mat &sum); -
int getblockSum(Mat &sum, int x1, int y1, int x2, int y2, int i); -
int main(int argc, char** argv) { -
Mat src = imread("D:/vcprojects/images/yuan_test.png"); -
if (src.empty()) { -
printf("could not load image... "); -
return -1; -
} -
namedWindow("input", CV_WINDOW_AUTOSIZE); -
imshow("input", src); -
-
namedWindow("output", CV_WINDOW_AUTOSIZE); -
-
// 計算積分圖 -
Mat sum, sqrsum; -
integral(src, sum, sqrsum, CV_32S, CV_32F); -
-
// 積分圖應用 -
int type = 0; -
while (true) { -
char c = waitKey(100); -
if (c > 0) { -
type = (int)c; -
printf("c : %d ", type); -
} -
-
if (c == 27) { -
break; // ESC -
} -
if (type == 49) { // 數字鍵 1 -
blur_demo(src, sum); -
} -
else if (type == 50) { // 數字鍵 2 -
edge_demo(src, sum); -
} -
else { -
blur_demo(src, sum); -
} -
} -
-
waitKey(0); -
return 0; -
} -
-
void blur_demo(Mat &image, Mat &sum) { -
int w = image.cols; -
int h = image.rows; -
Mat result = Mat::zeros(image.size(), image.type()); -
int x2 = 0, y2 = 0; -
int x1 = 0, y1 = 0; -
int ksize = 5; -
int radius = ksize / 2; -
int ch = image.channels(); -
int cx = 0, cy = 0; -
for (int row = 0; row < h + radius; row++) { -
y2 = (row + 1)>h ? h : (row + 1); -
y1 = (row - ksize) < 0 ? 0 : (row - ksize); -
for (int col = 0; col < w + radius; col++) { -
x2 = (col + 1)>w ? w : (col + 1); -
x1 = (col - ksize) < 0 ? 0 : (col - ksize); -
cx = (col - radius) < 0 ? 0 : col - radius; -
cy = (row - radius) < 0 ? 0 : row - radius; -
int num = (x2 - x1)*(y2 - y1); -
for (int i = 0; i < ch; i++) { -
// 積分圖查找和表,計算卷積 -
int s = getblockSum(sum, x1, y1, x2, y2, i); -
result.at<Vec3b>(cy, cx)[i] = saturate_cast(s / num); -
} -
} -
} -
imshow("output", result); -
imwrite("D:/result.png", result); -
} -
-
/** -
* 3x3 sobel 垂直邊緣檢測演示 -
*/ -
void edge_demo(Mat &image, Mat &sum) { -
int w = image.cols; -
int h = image.rows; -
Mat result = Mat::zeros(image.size(), CV_32SC3); -
int x2 = 0, y2 = 0; -
int x1 = 0, y1 = 0; -
int ksize = 3; // 算子大小,可以修改,越大邊緣效應越明顯 -
int radius = ksize / 2; -
int ch = image.channels(); -
int cx = 0, cy = 0; -
for (int row = 0; row < h + radius; row++) { -
y2 = (row + 1)>h ? h : (row + 1); -
y1 = (row - ksize) < 0 ? 0 : (row - ksize); -
for (int col = 0; col < w + radius; col++) { -
x2 = (col + 1)>w ? w : (col + 1); -
x1 = (col - ksize) < 0 ? 0 : (col - ksize); -
cx = (col - radius) < 0 ? 0 : col - radius; -
cy = (row - radius) < 0 ? 0 : row - radius; -
int num = (x2 - x1)*(y2 - y1); -
for (int i = 0; i < ch; i++) { -
// 積分圖查找和表,計算卷積 -
int s1 = getblockSum(sum, x1, y1, cx, y2, i); -
int s2 = getblockSum(sum, cx, y1, x2, y2, i); -
result.at<Vec3i>(cy, cx)[i] = saturate_cast(s2 - s1); -
} -
} -
} -
Mat dst, gray; -
convertScaleAbs(result, dst); -
normalize(dst, dst, 0, 255, NORM_MINMAX); -
cvtColor(dst, gray, COLOR_BGR2GRAY); -
imshow("output", gray); -
imwrite("D:/edge_result.png", gray); -
} -
-
int getblockSum(Mat &sum, int x1, int y1, int x2, int y2, int i) { -
int tl = sum.at<Vec3i>(y1, x1)[i]; -
int tr = sum.at<Vec3i>(y2, x1)[i]; -
int bl = sum.at<Vec3i>(y1, x2)[i]; -
int br = sum.at<Vec3i>(y2, x2)[i]; -
int s = (br - bl - tr + tl); -
return s; -
}
這里最重要的是要注意到上面的圖示,積分圖對象的Mat(1,1)對應實際圖像Mat(0,0),如果不加處理的話會導致結果有明顯的中心遷移。edge_demo實現了積分圖查找提取圖像邊緣、blur_demo函數實現積分圖查找圖像均值模糊,getblockSum函數實現和表查找功能,運行顯示:
原圖:
模糊效果

邊緣效果

審核編輯 :李倩
-
圖像
+關注
關注
2文章
1096瀏覽量
42331 -
函數
+關注
關注
3文章
4417瀏覽量
67521 -
OpenCV
+關注
關注
33文章
652瀏覽量
44801
原文標題:OpenCV中積分圖介紹與應用
文章出處:【微信號:CVSCHOOL,微信公眾號:OpenCV學堂】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
OpenCV首次到訪奧比中光并展開深度交流
沒有專利的opencv-python 版本
機器視覺雙雄YOLO 和 OpenCV 到底有啥區別?別再傻傻分不清!
零成本鋼鐵俠手套!樹莓派+OpenCV 秒變手勢遙控器!
如何使用樹莓派與OpenCV實現面部和運動追蹤的云臺系統?
如何使用樹莓派+OpenCV實現姿態估計和面部特征點追蹤?
如何板端編譯OpenCV并搭建應用--基于瑞芯微米爾RK3576開發板
ElfBoard技術貼|如何在【RK3588】ELF 2開發板中安裝openCV4以及第三方庫contrib
OpenCV中積分圖函數與應用
評論