图像的卷积操作

图像的卷积操作原理:给定一个奇数尺寸大小的卷积核,对图像进行卷积操作。因为使用奇数尺寸大小的卷积核,其锚点正好在卷积核正中央的位置。如下图中间画了一个锚的就是锚点使锚点覆盖在待计算像素上面,然后计算像素值与被覆盖的卷积核中的值的乘积和。将这个和赋值给当前像素,这就是卷积的过程。公式如下所示此处会有一个问题,如果锚点落在第一个像素点(1,1)上,卷积核当中锚点左侧和上方的卷积值超出了图像的边界外…

大家好,又见面了,我是你们的朋友全栈君。

原理:

给定一个奇数尺寸大小的卷积核,对图像进行卷积操作。

因为使用奇数尺寸大小的卷积核,其锚点正好在卷积核正中央的位置。

如下图
在这里插入图片描述

中间画了一个锚的就是锚点

使锚点覆盖在待计算像素上面,然后计算像素值与被覆盖的卷积核中的值的乘积和。将这个和赋值给当前像素,这就是卷积的过程。

公式如下所示

在这里插入图片描述

此处会有一个问题,如果锚点落在第一个像素点(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() 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140737.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • MQ学习笔记

    MQ学习笔记一、为什么要使用MQ?其实这里要讲的就是使用MQ的好处,MQ的的使用场景有很多,但是比较核心的有3个:解耦、异步、削峰1. 解耦例如:A系统要发送数据到B、C、D三个系统,通过接口调用发送。假如现在又添加了一个E系统,也要数据,A系统需要修改;B系统说我现在不需要这个数据了,A系统还是要修改。这种情况下,A系统的维护者肯定很崩溃。其实这个调用是不需要直接同步调用接口的,如…

    2022年6月13日
    69
  • opencv滤波、图像形运算、Sober算子

    opencv滤波、图像形运算、Sober算子1.opencv中滤波操作:ksize必须是奇数1.均值操作:选定图像上的行数和列数,求出总和,除以总个数,然后将这个数放到这个选定区的中间区域中。数学表达式:4上的值=(5+6+6+7+4+…..+55)/25;函数:result=cv2.blur(src,ksize)importcv2o=cv2.imread(‘D:\cc1\lenacolor.png’)#进行图片的读取s1=cv2.blur(o,(10,10))#进行均值操作cv2.imshow(‘oringle’,o)#进行

    2022年7月14日
    18
  • 使用SplitContainer控件

    使用SplitContainer控件在Windows资源管理器中,当把鼠标指针移动到TreeView控件和ListView控件之间时,可以左右拖动鼠标调整TreeView控件和ListView控件在主窗口中的大小比例,以适应不同显示内容

    2022年7月1日
    27
  • pycharm2021.12.12激活-激活码分享

    (pycharm2021.12.12激活)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月30日
    122
  • Java设计模式之状态模式

    本文属于”23种设计模式”系列,介绍状态模式。

    2022年3月11日
    47
  • 用opencv的dnn模块做yolov5目标检测[通俗易懂]

    用opencv的dnn模块做yolov5目标检测[通俗易懂]最近在微信公众号里看到多篇讲解yolov5在openvino部署做目标检测文章,但是没看到过用opencv的dnn模块做yolov5目标检测的。于是,我就想着编写一套用opencv的dnn模块做yolov5目标检测的程序。在编写这套程序时,遇到的bug和解决办法,在这篇文章里讲述一下。在yolov5之前的yolov3和yolov4的官方代码都是基于darknet框架的实现的,因此opencv的dnn模块做目标检测时,读取的是.cfg和.weight文件,那时候编写程序很顺畅,没有遇到bug。但是yolo

    2022年10月13日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号