大家好,又见面了,我是你们的朋友全栈君。
原理:
给定一个奇数尺寸大小的卷积核,对图像进行卷积操作。
因为使用奇数尺寸大小的卷积核,其锚点正好在卷积核正中央的位置。
如下图
中间画了一个锚的就是锚点
使锚点覆盖在待计算像素上面,然后计算像素值与被覆盖的卷积核中的值的乘积和。将这个和赋值给当前像素,这就是卷积的过程。
公式如下所示
此处会有一个问题,如果锚点落在第一个像素点(1,1)上,卷积核当中锚点左侧和上方的卷积值超出了图像的边界外,怎么处理?
这里使用最原始的办法,即将待处理的图片增加一圈边缘,这个边缘正好宽度正好是卷积核尺寸除以2再取整的值,这样一个图像就多了一圈像素值为0的黑框。
可以进行卷积操作了。
在opencv 的函数库当中,有filter2D这么个函数,咱们现在山寨他一个!
代码:
void Filter2D(const Mat &src, Mat &dst,int ksize,short *kernel)//参数分别为原始图像,目标图像,卷积核尺寸,卷积核,只读入16位图像哦! {
CV_Assert(ksize % 2 == 1); Mat tmp; int len = ksize / 2; tmp.create(Size(src.cols + len, src.rows + len), src.type());//添加边框 dst.create(Size(src.cols, src.rows), src.type()); int channel = src.channels(); uchar *ps = src.data; uchar *pt = tmp.data; for (int row = 0; row < tmp.rows; row++)//添加边框的过程 {
for (int col = 0; col < tmp.cols; col++) {
for (int c = 0; c < channel; c++) {
if (row >= len && row < tmp.rows - len && col >= len && col < tmp.cols - len) pt[(tmp.cols * row + col)*channel + c] = ps[(src.cols * (row - len) + col - len) * channel + c]; else pt[(tmp.cols * row + col)*channel + c] = 0; } } } uchar *pd = dst.data; pt = tmp.data; for (int row = len; row < tmp.rows - len; row++)//卷积的过程 {
for (int col = len; col < tmp.cols -len; col++) {
for (int c = 0; c < channel; c++) {
short t = 0; for (int x = -len; x <= len; x++) {
for (int y = -len; y <= len; y++) {
t += kernel[ (len+x) * ksize + y + len] * pt[((row + x) * tmp.cols + col + y) * channel + c]; } } pd[(dst.cols * (row - len) + col - len) * channel + c] = saturate_cast<ushort> (t);//防止数据溢出ushort是16为数据 } } } } int main() {
ios::sync_with_stdio(false); Mat src = imread("src.jpg"); Mat dst; short m[9] = {
0, -1, 0 ,-1,4,-1, 0 ,-1,0}; Filter2D(src, dst, 3, m); imshow("src", src); imshow("dst", dst); waitKey(); system("pause"); return 0; }
结果:
src图像是
卷积后的图像
这里使用的卷积核是
[0,-1,0]
[-1,4,-1]
[0,-1,0]
使用python来执行同样的操作,结果是一样的哦!
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('src.jpg') a=[ [0,-1,0], [-1,4,-1], [0,-1,0] ] kernel = np.array(a) dst = cv2.filter2D(img,-1,kernel) cv2.imshow('src',img) cv2.imshow("dst",dst) cv2.waitKey()
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/140737.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...