搜索
bottom↓
回复: 61

我的硕士毕业论文,机器视觉相关,有相机操作、MATLAB和OpenCV图像处理

  [复制链接]

出0入0汤圆

发表于 2012-1-4 08:32:31 | 显示全部楼层 |阅读模式
很多产品相关的地方语焉不详,不好意思是导师的要求,有的公式经过处理

不过有的技术细节反而是可以详细说说的,比如MATLAB和OpenCV的图像处理,比如MATLAB+OpenCV+VC的联合编程,比如映美精相机的操作

OpenCV我用的比较熟,这个工具非常好用

论文题目:
《卷烟纸罗纹强度检测方法研究与系统设计》

该系统除了机械部分,其他都是我做的

点击此处下载 ourdev_710162K0VQX9.pdf(文件大小:16.88M) (原文件名:卷烟纸罗纹强度检测方法研究与系统设计.pdf)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2012-1-4 08:36:31 | 显示全部楼层
有的技术细节论文里没写,这里小小补充一下,直上代码!:


用OpenCV求解最大连通域




本程序的主要结构是:
1.读彩色bmp文件,提取Green通道
2.中值滤波,Otsu二值化
3.形态学操作去除小细节
4.标注连通域
5.求解最大连通域


#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
#include <vector>
#include <algorithm>
using namespace std;

///////////////////////////////////////////////

void CMy20111114qian的matlab程序转opencvDlg::OnBnClickedButton1()
{
    IplImage *src = cvLoadImage("before.bmp", CV_LOAD_IMAGE_COLOR);//读取图像文件

    cvNamedWindow("origin");
    cvShowImage("origin", src);//显示原始图像

    //摄像机保存的图像是32位的,有R、G、B和Alpha通道
    //图像中实际存储顺序是B、G、R
    IplImage *blue    = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);//制作一个单通道图像
    IplImage *green = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);//制作一个单通道图像
    IplImage *red    = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);//制作一个单通道图像

    cvSplit(src, blue, green, red, NULL);//分割颜色通道

    cvSmooth(green, green, CV_MEDIAN, 7);//7*7中值滤波

    cvThreshold(green, green, 0.0, 255.0, CV_THRESH_BINARY | CV_THRESH_OTSU);// OTSU法二值化

    {
        IplConvKernel *element  
            = cvCreateStructuringElementEx(5, 5, 0, 0, CV_SHAPE_ELLIPSE);//定义形态学结构指针

        cvMorphologyEx(green, green, NULL, element, CV_MOP_OPEN);//开运算,去除比结构元素小的亮点

        cvReleaseStructuringElement(&element);
    }

    cvNamedWindow("binary");
    cvShowImage("binary", green);//显示二值化图像

    {
        int color = 254;// 从254开始,因此连通域不能多于253个

        CvSize sz = cvGetSize(green);
        int w;
        int h;

        for (w=0; w<sz.width; w++)
        {
            for (h=0; h<sz.height; h++)
            {
                if (color > 0)
                {
                    if (CV_IMAGE_ELEM(green, unsigned char, h, w) == 255)
                    {
                        cvFloodFill(green, cvPoint(w,h), CV_RGB( color,color,color));//把各连通域标记上颜色
                        color--;
                    }
                }
            }
        }

        cvNamedWindow("labeled");
        cvShowImage("labeled", green);//显示标记后的图像

        int colorsum[255] = {0};
        for (w=0; w<sz.width; w++)
        {
            for (h=0; h<sz.height; h++)
            {
                if (CV_IMAGE_ELEM(green, unsigned char, h, w) > 0)//不对0值计数,不可能为255
                {
                    colorsum[CV_IMAGE_ELEM(green, unsigned char, h, w)]++;//统计每种颜色的数量
                }
            }
        }

        vector<int> v1(colorsum, colorsum+255);//用数组初始化vector
        int maxcolorsum = max_element(v1.begin(), v1.end()) - v1.begin();//求出最多数量的颜色

        for (w=0; w<sz.width; w++)
        {
            for (h=0; h<sz.height; h++)
            {
                if (CV_IMAGE_ELEM(green, unsigned char, h, w) == maxcolorsum)
                {
                    CV_IMAGE_ELEM(green, unsigned char, h, w) = 255;//只把最多数量的颜色标为255
                }
                else
                {
                    CV_IMAGE_ELEM(green, unsigned char, h, w) = 0;//其他标为0
                }
            }
        }

        cvNamedWindow("最大连通域");
        cvShowImage("最大连通域", green);//显示最大连通域
    }

    cvReleaseImage(&src);
    cvReleaseImage(&blue);
    cvReleaseImage(&green);
    cvReleaseImage(&red);
}

出0入0汤圆

 楼主| 发表于 2012-1-4 08:37:34 | 显示全部楼层
利用OpenCV进行邻域平均





在数据采集系统中,对采集到的数据进行平滑处理是一种很常用的操作,一般是设置一 个滑动窗口,对该窗口中的数据去除最大值和最小值,将剩下的值取平均值

在这里我们就不用自己编写邻域平均程序了,直接采用OpenCV中提供的函数,尽量利用 已有的资源,把不可避免的编程工作降到最低

使用cvSmooth函数,可选择高斯平滑、邻域平均、中值平滑等
若是使用Filter2D函数,还可以自定义平滑方式,例如设定核函数可以实现如下功能:
x = double(8*x + 4*x[i-1] + 2*x[i-2] + x[i-3])/(8+4+2+1)

以下程序中,q1是原始数据,q2是邻域平均后的数据:

/////////////////////////////////////////////////

#include <deque>
using namespace std;
deque<float> q1(600);//原始数据,十分钟
deque<float> q2(600);//邻域平均后的数据


void CMy20111116_PCR曲线绘制Dlg::OnBnClickedButton2()
{
    int n = GetDlgItemInt(IDC_EDIT1);//几点平滑

    CvMat* mat = cvCreateMat(1, 600, CV_32FC1);

    for (int i=0; i<600; i++)
    {
        cvmSet(mat, 0, i, q1);
    }

    cvSmooth(mat, mat, CV_BLUR, n);

    for (int i=0; i<600; i++)
    {
        q2.pop_front();
        q2.push_back(cvmGet(mat, 0, i));
    }

    cvReleaseMat(&mat);
}

出0入0汤圆

 楼主| 发表于 2012-1-4 08:39:15 | 显示全部楼层
VC + OpenCV + MATLAB 联合编程






使用的软件版本分别是:Visual C++ 2005、OpenCV 2.0、MATLAB2009a。
  
假设我们已经有了一个封装好的调用MATLAB中函数的函数(请自行上网搜索MATLAB与VC联合编程的文章):
double MATLAB_myfunc1(double * matrix, int row, int col)
函数中的参数分别代表数据块起始地址、行、列。
  
OpenCV及MATLAB编程的细节这里就省略不写了,在VC中调用OpenCV再调用MATLAB函数的用法如下:
  
IplImage *iplgray = cvCreateImage(cvSize(Width,Height),IPL_DEPTH_8U,1);   //创建8bit灰度图像
...//读取图像放入iplgray
IplImage *iplgraydouble = cvCreateImage(cvSize(Width,Height),IPL_DEPTH_64F,1);  //创建双精度矩阵,因为我们的MATLAB函数的参数是double型矩阵
cvConvert(iplgray,iplgraydouble);   // 类型转换
IplImage *iplgraydoubletranspose = cvCreateImage(cvSize(Height,Width),IPL_DEPTH_64F,1);   // 用于存放转置后的矩阵,注意高宽参数
cvTranspose(iplgraydouble,iplgraydoubletranspose);   // 矩阵转置,因为在OpenCV中矩阵数据按行存储,而MATLAB中是按列存储
double dd = MATLAB_myfunc1((double*)iplgraydoubletranspose->imageData,
iplgraydoubletranspose->height,iplgraydoubletranspose->width);   // 调用
MATLAB中编写的函数

  
最需要注意的就是OpenCV和MATLAB中数据存储的方向不同。

为什么要联合编程呢,因为有的操作在MATLAB中很容易实现,在OpenCV或VC里却要花很
大篇幅,这样联合调用的话就省事多了。
  
但是也有缺点,MATLAB调用很慢,而且电脑上需要安装了对应版本的MATLAB,因此推荐
这种联合调用的方法用于算法的研究阶段,制作最终程序时还是建议用OpenCV或VC。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 18:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表