2020-03-09 19:45:14 qq_43409114 阅读数 24
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4439 人正在学习 去看看 贾志刚

一、形态学的基本概念

基本思想:用一定形态的结构元素去度量和提取图像中的对应形状,从而达到分析和识别的目的。

适用范围:图像的分割、特征抽取、边界检测

作用:这门学科在计算机文字识别,计算机显微图像分析,医学图像处理,工业检测等方面都取得了非常成功的应用。形态学方法已成为图像应用领域工程技术人员的必备工具。目前,有关数学形态学的技术和应用正在不断地研究和发展。

主要的数学基础:集合论

结构元素:形态学变换中的基本元素,是为了探测图像的某种结构信息而设计的特定形状和尺寸的图像,称为收集图像的结构信息的探针

结构元素类型:圆形、方型、线形、可以携带多汁知识进行探测。

利用上述结构元素在图像中逐点移动,看看这个像素满不满足某个结构的要求

结构元素本身就是图像

二、形态学算子

形态学运算:二值腐蚀、膨胀、二值开闭运算、骨架抽取、击中击不中变换等

形态学四个基本算子:膨胀、腐蚀、开启、闭合

腐蚀运算

什么是腐蚀运算呢?
概念:有一结构元素B和一副图像X,现在讲结构元素B逐点遍历,如果该点和其邻域与结构元素B全等,则保留该店,否则舍弃该点。

腐蚀运算有什么作用呢?

  • 可以消除物体边界点,使边界向内部收缩。
  • 可以把小于结构元素的物体去掉,选取不同大小的结构元素,去除不同大小 的物理。

水平方向的腐蚀
其结构元素形式如下
在这里插入图片描述
垂直方向的腐蚀
其结构元素如下
在这里插入图片描述
全方向腐蚀
在这里插入图片描述

代码实现
    # 图像的腐蚀
    def imageErosion(self,v,count=1):
        for i in range(0,count):
            self.__imageErosion__(v)
    def __imageErosion__(self,v): #参数v为结构元素
        width = len(v) #首先判断结构元素的大小
        v_w=int(width/2) #得到中心点到边界的大小
        img_buf=np.copy(self.Img) #开辟一个图像缓存区
        # 可以使用模板的区域进行遍历
        for y in range(v_w,self.f_height-v_w):
            for x in range(v_w,self.f_width-v_w):
                v_values=self.Img[y-v_w:y+v_w+1,x-v_w:x+v_w+1,0] # 得到所有像素元的值
                if self.Img[y,x,0]==255:
                    continue
                # 然后比较该像素点是否符合结构元素的特点
                flag=False
                for y_i in range(0,len(v_values)):
                    for x_i in range(0,len(v_values[y_i])):
                        v1=v[y_i][x_i]
                        p1=v_values[y_i][x_i]
                        if v1==0:
                            continue
                        elif v1==1 and p1==255:
                            flag=True
                            break
                    if flag:
                        break
                if flag==True:
                    img_buf[y,x,:]=255
        self.Img=img_buf

原图如下
在这里插入图片描述
效果图如下(水平腐蚀2次)
在这里插入图片描述

膨胀运算

什么是膨胀运算呢?
与腐蚀相反

注意:膨胀运算的结构元素与腐蚀运算的结构元素是一一对应的,可以通用

对二值化物体边界点扩充,将与物体接触的所有背景点合并到该物体中,使边界向外部扩展。
如果两个物体之间的距离比较近,可能会把两个物体连通到一起。
对填补图像分割后的物体空洞有作用。

注意腐蚀和膨胀并不互为逆运算,但是可以级连结合使用
在这里插入图片描述
简单点说,腐蚀作用要求图像上的某点元素的领域完全与结构元素相同才保留,而膨胀作用只要求某点元素的领域与结构元素有相交部分就保留,这里所指的保留是如果该点位背景点,则将其改变为物体点,如果是物体点,则还是不变。
在这里插入图片描述

在这里插入图片描述

代码实现
    # 图像膨胀
    def imageDilation(self,v,count=1):
        for i in range(0,count):
            self.__imageDilation__(v)
    def __imageDilation__(self,v):
        width = len(v) #首先判断结构元素的大小
        v_w=int(width/2) #得到中心点到边界的大小
        img_buf=np.copy(self.Img) #开辟一个图像缓存区
        # 可以使用模板的区域进行遍历
        for y in range(v_w,self.f_height-v_w):
            for x in range(v_w,self.f_width-v_w):
                v_values=self.Img[y-v_w:y+v_w+1,x-v_w:x+v_w+1,0] # 得到所有像素元的值
                flag = False # 设置标记为FALSE
                '下面对抽取的像素进行遍历'
                for y_i in range(0,len(v_values)):
                    for x_i in range(0,len(v_values[y_i])):
                        v1=v[y_i][x_i] # 结构元素中的值
                        p1=v_values[y_i][x_i] # 抽取出来的像素里的值
                        if v1==0: #如果结构元素中的值为0,则说明这个地方为NULL。直接忽略
                            continue
                        elif (v1==1 and p1==0): #否则的话,判断结构元素中的点是否为物体,如果是,则满住膨胀条件
                            flag=True
                            break
                    if flag== True:
                        img_buf[y, x, :] = 0
                        break

        self.Img=img_buf

原图如下
在这里插入图片描述
膨胀之后的图像(全方向腐蚀,5*5的结构元素大小)
在这里插入图片描述

三、图像的开启与闭合

基本概念
有膨胀和腐蚀两个运算的复合与集合操作组成的所有运算构成。

开运算:先对图像进行腐蚀运算,然后再对图像进行膨胀运算(使用同一结构元素)

闭运算:先对图像进行膨胀运算,然后再对图像进行腐蚀运算(使用同一结构元素)

作用
开运算:能够去除孤立的小点,毛刺和小桥(连通两片区域的小点),消除小物体,平滑较大物体的边界。同时并不明显改变其面积。但是开运算后的图像与原图像不等

闭运算:先膨胀、后腐蚀,其功能是用来填充物体内细小的空洞,弥合小裂缝,同时并不明显改变其面积。但是闭运算后的图像与原图像不等

2019-12-17 21:44:10 weixin_41629698 阅读数 77
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4439 人正在学习 去看看 贾志刚

图像处理-形态学腐蚀

python的opencv库提供了强大的图像处理功能,比如图像反转,图像色彩变换以及图像的边缘提取等便捷方法。
本次分享内容包括opencv形态学腐蚀,图像高斯处理用到的库有opencv库以及提供科学计算的numpy包

处理图像

需要将此图像的的圆圈部分去除,保留文字不变
在这里插入图片描述
对于少量的图片,我们可以借助其他工具可以很轻松的解决,但是对于大量如此的图像来说,ps等工具显得力不从心,可以考虑借助程序的方式来解决。

形态学腐蚀

含义:可以理解为,移动结构B,如果结构B与结构A的交集完全属于结构A的区域内,则保存该位置点,所有满足条件的点构成结构A被结构B腐蚀的结果。

其实也可以简单理解为在一定半径范围内,两根粗细不同的线,在同等情况下,细的会被腐蚀去除。使用形态学腐蚀后效果如下
在这里插入图片描述
处理代码如下:

src = cv.imread("img.jpg")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
#gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
#gray = cv.GaussianBlur(gray, (9, 9), 2, 2)
# 二值化图像
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
gray = cv.GaussianBlur(gray, (9, 9), 4, 4)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("input", binary)
# 使用3x3结构元素进行膨胀与腐蚀操作
se = cv.getStructuringElement(cv.MORPH_RECT, (3,3), (-1, -1)) #结构元素
dilate = cv.dilate(binary, se, None, (-1, -1),2 )
# 显示
cv.imshow("dilate", dilate)
cv.imwrite("dilate.png", dilate)

不同的图片可以通过调节相应参数以实现。
另外还可以利用Hough圆检测方法,检测到圆后,直接替换圆像素即可实现圆去除,有兴趣的小伙伴,可以交流一下!!!

2020-01-26 15:42:33 qq_36793268 阅读数 54
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4439 人正在学习 去看看 贾志刚

形态学处理应用


找出图中的文字

在这里插入图片描述
效果

在这里插入图片描述

思路

利用腐蚀膨胀和图像重建,在文字所在地方利用重建,找出文字

步骤

  1. 先把图像转换为灰度图
    在这里插入图片描述

  2. 再把图像转换为二值图
    观察灰度图,发现灰色部分较多,而字的白色较明显,可以利用imbinarize的参数,将偏灰的一些元素变为黑色,将特别白的地方转化为白色。
    在这里插入图片描述
    imbinarize 函数的使用具体见这里
    代码:

    clear,clc,close all;
    f=imread('ws.jpg');
    g=rgb2gray(f);
    imshow(g);
    bw_just=imbinarize(g,0.99);       %将大于灰度图取值的0.99的部分转换为白色,小于的转换为黑色
    figure,imshow(bw_just);
    
  3. 去除多余的小对象
    通过观察可以看到,在字的旁边有很多杂乱的小对象,可以用 bwareaopen 去除。

    在这里插入图片描述

    新增代码为:

    bw_ao=bwareaopen(bw_just,100);  %去除大小小于100的对象
    figure,imshow(bw_ao);	
    
  4. 利用默认参数将原图转换为二值图
    本例的目的为得到中间的几个字,上一步所处理得到的图像为字的一部分,自然可以想到利用在原图的重建,得到字体,因此先将原图转换为二值图,便可得到清晰的四个字,如下所示:
    在这里插入图片描述新增代码为:

    b=imbinarize(g,0.5);
    figure,imshow(b),title('原图');
    
  5. 膨胀连接所有字体的小部分
    观察可以发现,每个字体的上下或左右结构可能有间隔,最好的办法是对上一步得到的二值图进行膨胀,让每个字都连接成一个连通的部分,然后利用第三步的少部分字体的图在连接好的字体上重建,可以得到膨胀的字体。
    在这里插入图片描述
    新增代码为:

    fd=imdilate(b,strel("disk",2));
    bw_re=imreconstruct(bw_ao,fd);
    figure,imshow(bw_re),title('膨胀后重建');
    
  6. 观察可知,只需要在二值图上进行重建,即可找出原字体的图像
    在这里插入图片描述

本例代码为:

clear,clc,close all;
f=imread('ws.jpg');
g=rgb2gray(f);
imshow(g);

bw_just=imbinarize(g,0.99);
figure,imshow(bw_just);

bw_ao=bwareaopen(bw_just,100);
figure,imshow(bw_ao);

b=imbinarize(g,0.5);
figure,imshow(b),title('原图');

fd=imdilate(b,strel("disk",2));
bw_re=imreconstruct(bw_ao,fd);
figure,imshow(bw_re),title('膨胀后重建');

bw_rer=imreconstruct(bw_re,b);
figure,imshow(bw_rer);
2018-04-17 23:14:43 wsh596823919 阅读数 9401
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4439 人正在学习 去看看 贾志刚

GitHub地址:https://github.com/kevinten10/Image-Processing

 

1、选用合适的图像增强方法对以下给定图像进行增强操作以获取清晰图像;

2、对增强后的图像进行阈值处理,获得二值图像;

3、对二值图像进行形态学分析,提取有用信息区域(即只剩下字母和数字区域);

 

python程序:

import cv2
import numpy as np

# 二值形态学运算
def morphology(img):
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (20,14)) # 腐蚀矩阵
    iFushi = cv2.morphologyEx(img, cv2.MORPH_DILATE, kernel1)  # 对文字腐蚀运算
    cv2.imshow('fushi', iFushi)

    kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (40, 40))  # 膨胀矩阵
    iPengzhang = cv2.morphologyEx(iFushi, cv2.MORPH_ERODE, kernel2)  # 对背景进行膨胀运算
    cv2.imshow('pengzhang', iPengzhang)

    # 背景图和二分图相减-->得到文字
    jian = np.abs(iPengzhang - img)
    cv2.imshow("jian", jian)

    kernel3 = cv2.getStructuringElement(cv2.MORPH_RECT, (3 , 6))  # 膨胀
    iWenzi = cv2.morphologyEx(jian, cv2.MORPH_DILATE, kernel3)  # 对文字进行膨胀运算
    cv2.imshow('wenzi', iWenzi)

img = cv2.imread("TEST.tif")
# 1、消除椒盐噪声:
# 中值滤波器
median = cv2.medianBlur(img, 5)
# 消除噪声图
cv2.imshow("median-image", median)
# 转化为灰度图
Grayimg = cv2.cvtColor(median, cv2.COLOR_RGB2GRAY)
# 2、直方图均衡化:
hist = cv2.equalizeHist(Grayimg)
cv2.imshow('hist',hist)
# 3、二值化处理:
# 阈值为140
ret, binary = cv2.threshold(hist, 140, 255,cv2.THRESH_BINARY)
cv2.imshow("binary-image",binary)
# 二值形态处理
morphology(binary)

cv2.waitKey(0)

 

python程序步骤

 

(一)读入图像数据

使用OpenCV库读入tiff图像

img =cv2.imread("TEST.tif")

 

(二)消除椒盐噪声

使用5*5的中值滤波器滤除椒盐噪声

    median = cv2.medianBlur(img, 5)

(三)将图片数据类型转换为灰度图

    Grayimg = cv2.cvtColor(median, cv2.COLOR_RGB2GRAY)

 

(四)对图像进行直方图均衡化处理

    hist = cv2.equalizeHist(Grayimg)

 

(五)对直方图均衡化后进行二值化处理

选取阈值为140,大于140灰度值的像素置位255,低于140灰度值为0

    ret, binary = cv2.threshold(hist, 140, 255,cv2.THRESH_BINARY)

 

(六)对二值化图像进行腐蚀:

腐蚀掉文字部分得到背景部分,然后再对背景进行膨胀

使用(20,14)的矩形进行腐蚀操作:

kernel1= cv2.getStructuringElement(cv2.MORPH_RECT, (20,14))    iFushi = cv2.morphologyEx(img,cv2.MORPH_DILATE, kernel1)  

      

 

(七)将二分图像与腐蚀后的背景图相减

得到有效信息部分与部分噪声

    jian = np.abs(iPengzhang - img)

 

(八)对文字部分进行膨胀,得到较清晰的图像

    kernel3 =cv2.getStructuringElement(cv2.MORPH_RECT, (3 , 6))

    iWenzi =cv2.morphologyEx(jian, cv2.MORPH_DILATE, kernel3)

 

(1)滤除椒盐噪声可以使用均值滤波器或中值滤波器:

分析可知:均值滤波器会引入噪声的影响,而中值滤波器可以有效滤除噪声的影响。

试验了两种滤波器后,发现均值滤波器相较中值滤波器较模糊,所以滤除椒盐噪声使用中值滤波器会好一点

(2)选取合适的阈值进行二值化处理,要做到使信息清晰,并且能够有效地分割边界。

(3)选取合适的运算矩阵进行二值形态学的运算,通过腐蚀掉有效区域,然后进行图像减法的操作,可以得到被腐蚀的区域。

(4)对于断裂处,可采用长方形的矩阵进行膨胀处理,对于黏连处,同样可以采用长方形进行腐蚀处理

 

 

2019-09-01 19:51:41 webzhuce 阅读数 649
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4439 人正在学习 去看看 贾志刚

基本概念

        “骨架”是指一幅图像的骨骼部分,它描述物体的几何形状和拓扑结构,是重要的图像描绘子之一。计算骨架的过程一般称为“细化”或“骨架化”,在包括文字识别、工业零件形状识别以及印刷电路板自动检测在内的很多应用中,细化过程都发挥这关键作用。通常,对我们感兴趣的目标物体进行细化有助于突出目标的形状特点和拓扑结构并且减少冗余的信息。
在这里插入图片描述
这里给出细化算法
在这里插入图片描述

示例演示

        实现基于形态学的细化算法。与上面算法介绍不同,将白色作为前景,黑色作为背景。完整工程代码。

/*
 *only process binary image
 * white is foreground
*/
void Thining(const cv::Mat &src, cv::Mat &dst)
{

    //four conditions
    bool condition1 = false, condition2 = false, condition3 = false, condition4 = false;

    //n*n neighbours
    constexpr int N = 5;
    uchar neighbour[N][N];
    const int kOffset = N / 2;
    src.copyTo(dst);

    bool modified = true;
    while(modified)
    {
        modified = false;
        Mat img;
        dst.copyTo(img);

        for(int i = kOffset; i < (dst.rows - kOffset); i++)
        {
            for(int j = kOffset; j < (dst.cols - kOffset); j++)
            {
                if(dst.at<uchar>(i, j) == 0)
                    continue;

                condition1 = false;
                condition2 = false;
                condition3 = false;
                condition4 = false;

                //get N*N neighbours of current point
                //white : 0, black : 1
                for(int m = 0; m < N; m++)
                {
				    for(int n = 0; n < N; n++)
                    {
                        neighbour[m][n] = dst.at<uchar>(i + n - kOffset, j + m - kOffset) == 255 ? 1 : 0;
                    }
                }

                //2 <= NZ(P1) <=6
                int count = neighbour[1][1] + neighbour[1][2] + neighbour[1][3] +
                        neighbour[2][1] + neighbour[2][3] +
                        neighbour[3][1] + neighbour[3][2] + neighbour[3][3];
                if(count >= 2 && count <=6)
                    condition1 = true;

                //Z0(P1) == 1
                count = 0;
                if(neighbour[1][2] == 0 && neighbour[1][1] == 1)
                    count++;
                if(neighbour[1][1] == 0 && neighbour[2][1] == 1)
                    count++;
                if(neighbour[2][1] == 0 && neighbour[3][1] == 1)
                    count++;
                if(neighbour[3][1] == 0 && neighbour[3][2] == 1)
                    count++;
                if(neighbour[3][2] == 0 && neighbour[3][3] == 1)
                    count++;
                if(neighbour[3][3] == 0 && neighbour[2][3] == 1)
                    count++;
                if(neighbour[2][3] == 0 && neighbour[1][3] == 1)
                    count++;
                if(neighbour[1][3] == 0 && neighbour[1][2] == 1)
                    count++;
                if(count == 1)
                    condition2 = true;

                //P2*P4*P8 = 0 or Z0(P2) != 1
                if(neighbour[1][2] * neighbour[2][1] * neighbour[2][3] == 0)
                    condition3 = true;
                else
                {
                    count = 0;
                    if(neighbour[0][2] == 0 && neighbour[0][1] == 1)
                        count++;
                    if(neighbour[0][1] == 0 && neighbour[1][1] == 1)
                        count++;
                    if(neighbour[1][1] == 0 && neighbour[2][1] == 1)
                        count++;
                    if(neighbour[2][1] == 0 && neighbour[2][2] == 1)
                        count++;
                    if(neighbour[2][2] == 0 && neighbour[2][3] == 1)
                        count++;
                    if(neighbour[2][3] == 0 && neighbour[1][3] == 1)
                        count++;
                    if(neighbour[1][3] == 0 && neighbour[0][3] == 1)
                        count++;
                    if(neighbour[0][3] == 0 && neighbour[0][2] == 1)
                        count++;
                    if(count != 1)
                        condition3 = true;
                }

                //P2*P4*P6 = 0 or Z0(P4) != 1
                if(neighbour[1][2] * neighbour[2][1] * neighbour[3][2] == 0)
                    condition4 = true;
                else
                {
                    count = 0;
                    if(neighbour[1][1] == 0 && neighbour[1][0] == 1)
                        count++;
                    if(neighbour[1][0] == 0 && neighbour[2][0] == 1)
                        count++;
                    if(neighbour[2][0] == 0 && neighbour[3][0] == 1)
                        count++;
                    if(neighbour[3][0] == 0 && neighbour[3][1] == 1)
                        count++;
                    if(neighbour[3][1] == 0 && neighbour[3][2] == 1)
                        count++;
                    if(neighbour[3][2] == 0 && neighbour[2][2] == 1)
                        count++;
                    if(neighbour[2][2] == 0 && neighbour[1][2] == 1)
                        count++;
                    if(neighbour[1][2] == 0 && neighbour[1][1] == 1)
                        count++;
                    if(count != 1)
                        condition4 = true;
                }

                if(condition1 && condition2 && condition3 && condition4)
                {
                    img.at<uchar>(i, j) = 0;
                    modified = true;
                }
                else
                    img.at<uchar>(i, j) = 255;

            } // for columns
        } // for rows
        img.copyTo(dst);
    } //  for while
}

运行结果

在这里插入图片描述

没有更多推荐了,返回首页