2019-12-25 17:34:10 GL3_24 阅读数 34
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    56467 人正在学习 去看看 黄棒清

引言

在图像处理领域,我们都听说过边缘和纹理这两个概念,而且往往认为这两个概念是相同的,但其实不然。

一、概念理解

图像的边缘:图像中局部不连续的特征,一般根据灰度值来判断,图像边缘是灰度值发生突变的位置,也就是梯度值大的位置。
图像的纹理:图像中反复出现的局部模式和它们的排列规则,也可以认为是图像强度局部变化的重复模式。

二、实例解析(Halcon实例)

1.边缘
边缘是比较好理解的,就是灰度值发生了突变。
如一张灰度图像如下图所示。
在这里插入图片描述
进行边缘提取得到的边缘如下图所示。
在这里插入图片描述
2.纹理
纹理分析一般涉及到纹理分割以及纹理分类。本文以halcon中的texture_laws实例进行讲解。
texture即纹理,laws是一个人名,他发表了一篇博士论文。Laws, Kenneth Ivan. “Textured Image Segmentation”; Ph.D. Thesis, Department of Electrical Engineering, Image Processing Institute, University of Southern California, 1980。

texture_laws实例中可以实现根据自己选定的区域中的纹理信息进行训练,进而对整幅图像进行分割。
该实例中的原图如下所示。图中主要有两类特征:右上角以及右下角的森林、左上角左下角的草地。
在这里插入图片描述
如下图所示为不同滤波器对图像进行卷积得到的纹理信息,可以看出来纹理中存在一定的规律性,不同于边缘信息。
在这里插入图片描述
在这里插入图片描述
当选定原图中的森林区域进行训练时,分割得到的结果大部分都是森林区域。
在这里插入图片描述
当选定原图中的草地区域进行训练时,分割得到的结果大部分都是草地区域。
在这里插入图片描述

2018-06-06 18:11:06 qq_23926575 阅读数 10057
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    56467 人正在学习 去看看 黄棒清

提取方法:
灰度共生矩阵-python
灰度梯度共生矩阵–python

纹理特征

纹理特征刻画了图像中重复出现的局部模式与他们的排列规则,常用于图像分类和场景识别。其只能反映物体表面的特性,无法完全反映出物体的本质属性,所以仅仅利用纹理特征无法获得图像的高层次内容。
优点
1. 具有旋转不变性
2. 具有良好的抗噪性能。
缺点
1. 当图像的分辨率变化的时候,所计算出来的纹理可能会有较大偏差
2. 有可能受到光照、反射情况的影响
3. 从2-D图像中反映出来的纹理不一定是3-D物体表面真实的纹理

常用的纹理特征提取方法一般分为四大类:
1.基于统计的方法:灰度共生矩阵、灰度行程统计、灰度差分统计、局部灰度统计、半方差图、自相关函数等
优点:方法简单,易于实现。
缺点:无法利用全局信息,与人类视觉模型不匹配;计算复杂度较高,计算耗时。

较为经典的算法为灰度共生矩阵方法,其通过统计不同灰度值对的共现频率得到灰度共生矩阵,基于矩阵可计算出14种统计量:能量、熵、对比度、均匀性、相关性、方差、和平均、和方差、和熵、差方差、差平均、差熵、相关信息测度以及最大相关系数。
灰度梯度共生矩阵将图梯度信息加入到灰度共生矩阵中,综合利用图像的灰度与梯度信息,效果更好。图像的梯度信息一般通过梯度算子(也称边缘检测算子)提取,如sobel、canny、reborts等。

2.基于模型的方法:同步自回归模型、马尔可夫模型、吉布斯模型、滑动平均模型、复杂网络模型等
3.基于结构的方法:句法纹理分析、数学形态学法、Laws纹理测量、特征滤波器等
4.基于信号处理的方法:Radon变换、离散余弦变换、局部傅里叶变化、Gabor变换、二进制小波变换、树形小波分解等

参考:
灰度共生矩阵(GLCM)附Python代码
图像纹理特征总体简述

2011-11-04 18:44:07 myas0735 阅读数 1427
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    56467 人正在学习 去看看 黄棒清
数字图像处理的课程设计要做个图像搜索的专题,我们把整个系统的两个关键部分拿出来做一些调研和探索:图像的特征提取,图像的特征匹配。 

我们拟用基于纹理的特征提取和匹配,下面大致了解了一下这个方向的主要方法。 
纹理特征描述方法分类 

(1)统计方法统计方法的典型代表是一种称为灰度共生矩阵的纹理特征分析方法Gotlieb 和 Kreyszig 等人在研究共生矩阵中各种统计特征基础上,通过实验,得出灰度共生矩阵的四个关键特征:能量、惯量、熵和相关性。统计方法中另一种典型方法,则是从图像的自相关函数(即图像的能量谱函数)提取纹理特征,即通过对图像的能量谱函数的计算,提取纹理的粗细度及方向性等特征参数 

(2)几何法 

所谓几何法,是建立在纹理基元(基本的纹理元素)理论基础上的一种纹理特征分析方法。纹理基元理论认为,复杂的纹理可以由若干简单的纹理基元以一定的有规律的形式重复排列构成。在几何法中,比较有影响的算法有两种:Voronio 棋盘格特征法和结构法。 

(3)模型法 

模型法以图像的构造模型为基础,采用模型的参数作为纹理特征。典型的方法是随机场模型法,如马尔可夫(Markov)随机场(MRF)模型法和 Gibbs 随机场模型法 

(4)信号处理法 

纹理特征的提取与匹配主要有:灰度共生矩阵、Tamura 纹理特征、自回归纹理模型、小波变换等。 

灰度共生矩阵特征提取与匹配主要依赖于能量、惯量、熵和相关性四个参数。Tamura 纹理特征基于人类对纹理的视觉感知心理学研究,提出6种属性,即:粗糙度、对比度、方向度、线像度、规整度和粗略度。自回归纹理模型(simultaneous auto-regressive, SAR)是马尔可夫随机场(MRF)模型的一种应用实例。 
2015-10-26 16:54:51 zjsyhsl 阅读数 1062
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    56467 人正在学习 去看看 黄棒清

1 最近在看CUDA优化,看到纹理内存部分,可以使用纹理内存加速。
可是使用纹理内存后图像的处理速度反而变慢了。不解????

2 使用纹理内存代码
//Sobel 边缘提取 使用纹理内存

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>
#include<iostream>
#include"opencv2\opencv.hpp"

using namespace std;
using namespace cv;

//声明纹理参考系
texture<uchar,2,cudaReadModeElementType> tex;//2d texture

//设备端kernel函数
__global__ void ImgEdge_3x3_S_kernel(uchar* pImgOut,
                                       int nWidth,
                                       int nHeight,
                                       int nWidthStep)
{
    const int ix=blockIdx.x*blockDim.x+threadIdx.x;
    const int iy=blockIdx.y*blockDim.y+threadIdx.y;
    int point=ix+iy*nWidthStep;


    if(ix<nWidth&&iy<nHeight)
    {

        uchar point00=tex2D(tex,(float)ix-1,(float)iy-1);
        uchar point01=tex2D(tex,(float)ix,(float)iy-1);
        uchar point02=tex2D(tex,(float)ix+1,(float)iy-1);
        uchar point10=tex2D(tex,(float)ix-1,(float)iy);
        uchar point11=tex2D(tex,(float)ix,(float)iy);
        uchar point12=tex2D(tex,(float)ix+1,(float)iy);
        uchar point20=tex2D(tex,(float)ix-1,(float)iy+1);
        uchar point21=tex2D(tex,(float)ix,(float)iy+1);
        uchar point22=tex2D(tex,(float)ix+1,(float)iy+1);
        int Horz=point02+2*point12+point22-point00-2*point10-point20;
        int Vert=point00+2*point01+point02-point20-2*point21-point22;
        int Sum=abs(Horz)+abs(Vert);
        if(Sum>255) pImgOut[point]=255;
        else pImgOut[point]=(uchar)Sum;

    }
}
//设备端代码
double cudaImgEdge(uchar* pImgOut,
                     uchar* pImgIn,
                     int nWidth,
                     int nHeight,
                     int nWidthStep,
                     int nChannels)
{

    //准备设备端空间
    uchar* d_pImgInGPU;
    uchar* d_pImgOutGPU;
    cudaMalloc((void**)&d_pImgInGPU,nWidthStep*nHeight*sizeof(uchar));
    cudaMalloc((void**)&d_pImgOutGPU,nWidthStep*nHeight*sizeof(uchar));
    //数据初始化
    cudaMemcpy(d_pImgInGPU,pImgIn,nWidthStep*nHeight*sizeof(uchar),cudaMemcpyHostToDevice);
    cudaMemset(d_pImgOutGPU,0,nWidthStep*nHeight*sizeof(uchar));
    //建立CUDA二维数组
    cudaArray* cuArray;
    cudaChannelFormatDesc channelDesc=cudaCreateChannelDesc<uchar>();//CUDA数组的描述(组件数量和数据类型)
    cudaMallocArray(&cuArray,&channelDesc,nWidth,nHeight);
    cudaMemcpyToArray(cuArray,0,0,pImgIn,sizeof(uchar)*nWidth*nHeight,cudaMemcpyHostToDevice);
    //tex.AddressMode[0]=cudaAddressModeWrap;
    //tex.AddressMode[1]=cudaAddressModeWrap;
    //tex.normalized=true;
    //将显存数据与纹理绑定
    cudaBindTextureToArray(&tex,cuArray,&channelDesc);

    //启动kernel进行并行处理
    dim3 threads(16,16);
    dim3 grid((nWidth*nChannels+threads.x-1)/threads.x,(nHeight+threads.y-1)/threads.y);
    ImgEdge_3x3_S_kernel<<<grid,threads>>>(d_pImgOutGPU,nWidth,nHeight,nWidthStep);
    //解绑定
    cudaUnbindTexture(tex);
    cudaFreeArray(cuArray);
    //数据输出
    cudaMemcpy(pImgOut,d_pImgOutGPU,nWidthStep*nHeight*sizeof(uchar),cudaMemcpyDeviceToHost);
    //释放空间
    cudaFree(d_pImgInGPU);
    cudaFree(d_pImgOutGPU);
    return 0;
}

int main()
{
    //读入图片
    Mat ImgIn=imread("D:\\Images\\lenna1024.bmp",0);
    //检查是否成功
    if(ImgIn.empty())
    {
        cout<<"Can not load image"<<endl;
        return -1;
    }
    //读取图片数据结构
    Mat ImgOut=ImgIn.clone();
    int nWidth=ImgIn.cols;
    int nHeight=ImgIn.rows;
    int nWidthStep=ImgIn.step;
    int nChannels=ImgIn.channels();
    uchar* pSrc=ImgIn.data;
    uchar* pDest=ImgOut.data;

    //记录时间事件
    cudaEvent_t start,stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start,0);//开始时刻

    //调用边缘检测函数处理图片
    cudaImgEdge(pDest,pSrc,nWidth,nHeight,nWidthStep,nChannels);

    cudaEventRecord(stop,0);//结束时刻
    cudaEventSynchronize(stop);
    float elapsedTime;
    cudaEventElapsedTime(&elapsedTime,start,stop);
    printf("Time to generate:%f ms\n",elapsedTime);
    cudaEventDestroy(start);
    cudaEventDestroy(stop);

    //显示图片
    imshow("ImgIn",ImgIn);
    imshow("ImgOut",ImgOut);
    waitKey(0);
    return 0;
}

结果一个1024X1024的图像运行时间为127ms

3 未使用纹理内存代码

//Sobel 边缘提取 未使用纹理内存

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>
#include<time.h>
#include"opencv2\opencv.hpp"

using namespace std;
using namespace cv;


//设备端kernel函数
__global__ void ImgEdge_3x3_Sobel_kernel(uchar* pImgOut,
                                       uchar* pImgIn,
                                       int nWidth,
                                       int nHeight,
                                       int nWidthStep)
{
    const int ix=blockIdx.x*blockDim.x+threadIdx.x;
    const int iy=blockIdx.y*blockDim.y+threadIdx.y;

    const int ix_1=max(0,ix-1);
    const int ix1=min(nWidth-1,ix+1);
    const int iy_1=max(0,iy-1);
    const int iy1=min(nHeight-1,iy+1);

    if(ix<nWidth&&iy<nHeight)
    {

        uchar point00=pImgIn[iy_1*nWidthStep+ix_1];
        uchar point01=pImgIn[iy_1*nWidthStep+ix];
        uchar point02=pImgIn[iy_1*nWidthStep+ix1];
        uchar point10=pImgIn[iy*nWidthStep+ix_1];
        uchar point11=pImgIn[iy*nWidthStep+ix];
        uchar point12=pImgIn[iy*nWidthStep+ix1];
        uchar point20=pImgIn[iy1*nWidthStep+ix_1];
        uchar point21=pImgIn[iy1*nWidthStep+ix];
        uchar point22=pImgIn[iy*nWidthStep+ix1];
        int Horz=point02+2*point12+point22-point00-2*point10-point20;
        int Vert=point00+2*point01+point02-point20-2*point21-point22;
        int Sum=abs(Horz)+abs(Vert);
        if(Sum>255) pImgOut[iy*nWidthStep+ix]=255;
        else pImgOut[iy*nWidthStep+ix]=(uchar)Sum;

    }
}
//主机端函数
double cudaImgEdge(uchar* pImgOut,
                     uchar* pImgIn,
                     int nWidth,
                     int nHeight,
                     int nWidthStep,
                     int nChannels)
{

    //准备设备端空间
    uchar* d_pImgInGPU;
    uchar* d_pImgOutGPU;
    cudaMalloc((void**)&d_pImgInGPU,nWidthStep*nHeight*sizeof(uchar));
    cudaMalloc((void**)&d_pImgOutGPU,nWidthStep*nHeight*sizeof(uchar));
    //数据初始化
    cudaMemcpy(d_pImgInGPU,pImgIn,nWidthStep*nHeight*sizeof(uchar),cudaMemcpyHostToDevice);
    cudaMemset(d_pImgOutGPU,0,nWidthStep*nHeight*sizeof(uchar));


    //启动kernel进行并行处理
    dim3 threads(16,16);
    dim3 grid((nWidth*nChannels+threads.x-1)/threads.x,(nHeight+threads.y-1)/threads.y);
    ImgEdge_3x3_Sobel_kernel<<<grid,threads>>>(d_pImgOutGPU,d_pImgInGPU,nWidth,nHeight,nWidthStep);


    //数据输出
    cudaMemcpy(pImgOut,d_pImgOutGPU,nWidthStep*nHeight*sizeof(uchar),cudaMemcpyDeviceToHost);


    //释放空间
    cudaFree(d_pImgInGPU);
    cudaFree(d_pImgOutGPU);
    return 0;
}

int main()
{

    //读入图片
    Mat ImgIn=imread("D:\\Images\\lenna1024.bmp",0);
    //检查是否成功
    if(ImgIn.empty())
    {
        cout<<"Can not load image"<<endl;
        return -1;
    }
    //读取图片数据结构
    Mat ImgOut=ImgIn.clone();
    int nWidth=ImgIn.cols;
    int nHeight=ImgIn.rows;
    int nWidthStep=ImgIn.step;
    int nChannels=ImgIn.channels();
    uchar* pSrc=ImgIn.data;
    uchar* pDest=ImgOut.data;

    //记录时间事件
    cudaEvent_t start,stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start,0);//开始时刻

    //调用边缘检测函数处理图片
    cudaImgEdge(pDest,pSrc,nWidth,nHeight,nWidthStep,nChannels);

    cudaEventRecord(stop,0);//结束时刻
    cudaEventSynchronize(stop);
    float elapsedTime;
    cudaEventElapsedTime(&elapsedTime,start,stop);
    printf("Time to generate:%f ms\n",elapsedTime);
    cudaEventDestroy(start);
    cudaEventDestroy(stop);

    //显示图片
    imshow("ImgIn",ImgIn);
    imshow("ImgOut",ImgOut);

    waitKey(0);
    return 0;
}

同样的图片时间为17ms.

不知道使用的对不对。。

2019-08-06 21:02:14 Arthur_Holmes 阅读数 213
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    56467 人正在学习 去看看 黄棒清

依托纹理特征进行分割

磨皮除了滤波之外,还有更多的纹理合成

n_{i}是直方图对应灰度值的数量

从自相关到不相关

纹理方向与傅里叶能量集中方向呈90度角

环特征跟频率相关,所以跟纹理粗细相关

契特征则跟纹理方向相关

 

图像纹理特征总体简述

博文 来自: ajianyingxiaoqinghan
没有更多推荐了,返回首页