Zi 字媒體
2017-07-25T20:27:27+00:00
fanfuhan OpenCV 教學028 ~ opencv-028-圖像積分圖算法(應用在邊緣檢測)
資料來源: https://fanfuhan.github.io/
https://fanfuhan.github.io/2019/04/07/opencv-028/
GITHUB:https://github.com/jash-git/fanfuhan_ML_OpenCV
積分圖像是Crow在1984年首次提出,是為了在多尺度透視投影中提高渲染速度,是一種快速計算圖像區域和與平方和的算法。
其核心思想是對每個圖像建立自己的積分圖查找表,在圖像積分處理計算階段根據預先建立的積分圖查找表,直接查找從而實現對均值卷積線性時間計算,做到了卷積執行的時間與尺寸窗口大小的無關聯。
提取HAAR / SURF,二值圖像分析,圖像相似相關性NCC計算,圖像卷積快速計算等方面方面的應用,是圖像處理中的經典算法之一。
C++
#include
#include
using namespace std;
using namespace cv;
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() {
Mat src = imread("../images/test.png");
if (src.empty()) {
cout << "could not load image.." << endl;
}
imshow("input", src);
// 计算积分图
Mat sum, sqrsum;
integral(src, sum, sqrsum);
/*
* 积分图应用
*/
int type = 0;
// 模糊应用
blur_demo(src, sum);
// 边缘检测
edge_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(cy, cx)[i] = saturate_cast(s / num);
}
}
}
imshow("blur_demo", 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(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("edge_demo", gray);
}
int getblockSum(Mat &sum, int x1, int y1, int x2, int y2, int i) {
int tl = sum.at(y1, x1)[i];
int tr = sum.at(y2, x1)[i];
int bl = sum.at(y1, x2)[i];
int br = sum.at(y2, x2)[i];
int s = (br - bl - tr + tl);
return s;
}
Python
import cv2 as cv
import numpy as np
def get_block_sum(ii, x1, y1, x2, y2, index):
tl = ii[y1, x1][index]
tr = ii[y2, x1][index]
bl = ii[y1, x2][index]
br = ii[y2, x2][index]
s = (br - bl - tr + tl)
return s
def blur_demo(image, ii):
h, w, dims = image.shape
result = np.zeros(image.shape, image.dtype)
ksize = 15
radius = ksize // 2
for row in range(0, h + radius, 1):
y2 = h if (row + 1)> h else (row + 1)
y1 = 0 if (row - ksize) < 0 else (row - ksize)
for col in range(0, w + radius, 1):
x2 = w if (col + 1)>w else (col + 1)
x1 = 0 if (col - ksize) < 0 else (col - ksize)
cx = 0 if (col - radius) < 0 else (col - radius)
cy = 0 if (row - radius) < 0 else (row - radius)
num = (x2 - x1)*(y2 - y1)
for i in range(0, 3, 1):
s = get_block_sum(ii, x1, y1, x2, y2, i)
result[cy, cx][i] = s // num
cv.imshow("integral fast blur", result)
cv.imwrite("D:/result.png", result)
src = cv.imread("D:/images/test1.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
sum_table = cv.integral(src, sdepth=cv.CV_32S)
blur_demo(src, sum_table)
cv.waitKey(0)
cv.destroyAllWindows()
寫了
5860316篇文章,獲得
23313次喜歡