2016-06-15 20:46:49 GL_a_ 阅读数 310
  1. //图像的轮廓检测  
  2. //By MoreWindows (http://blog.csdn.net/MoreWindows)  
  3. #include <opencv2/opencv.hpp>  
  4. using namespace std;  
  5. #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  
  6. int main( int argc, char** argv )  
  7. {     
  8.     const char *pstrWindowsSrcTitle = "原图(http://blog.csdn.net/MoreWindows)";  
  9.     const char *pstrWindowsOutLineTitle = "轮廓图(http://blog.csdn.net/MoreWindows)";  
  10.       
  11.     const int IMAGE_WIDTH = 400;  
  12.     const int IMAGE_HEIGHT = 200;  
  13.   
  14.     // 创建图像  
  15.     IplImage *pSrcImage = cvCreateImage(cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 3);  
  16.     // 填充成白色  
  17.     cvRectangle(pSrcImage, cvPoint(0, 0), cvPoint(pSrcImage->width, pSrcImage->height), CV_RGB(255, 255, 255), CV_FILLED);  
  18.     // 画圆  
  19.     CvPoint ptCircleCenter = cvPoint(IMAGE_WIDTH / 4, IMAGE_HEIGHT / 2);  
  20.     int nRadius = 80;  
  21.     cvCircle(pSrcImage, ptCircleCenter, nRadius, CV_RGB(255, 255, 0), CV_FILLED);  
  22.     ptCircleCenter = cvPoint(IMAGE_WIDTH / 4, IMAGE_HEIGHT / 2);  
  23.     nRadius = 30;  
  24.     cvCircle(pSrcImage, ptCircleCenter, nRadius, CV_RGB(255, 255, 255), CV_FILLED);  
  25.     // 画矩形  
  26.     CvPoint ptLeftTop = cvPoint(IMAGE_WIDTH / 2 + 20, 20);  
  27.     CvPoint ptRightBottom = cvPoint(IMAGE_WIDTH - 20, IMAGE_HEIGHT - 20);  
  28.     cvRectangle(pSrcImage, ptLeftTop, ptRightBottom, CV_RGB(0, 255, 255), CV_FILLED);  
  29.     ptLeftTop = cvPoint(IMAGE_WIDTH / 2 + 60, 40);  
  30.     ptRightBottom = cvPoint(IMAGE_WIDTH - 60, IMAGE_HEIGHT - 40);  
  31.     cvRectangle(pSrcImage, ptLeftTop, ptRightBottom, CV_RGB(255, 255, 255), CV_FILLED);  
  32.     // 显示原图  
  33.     cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);  
  34.     cvShowImage(pstrWindowsSrcTitle, pSrcImage);  
  35.   
  36.   
  37.     // 转为灰度图  
  38.     IplImage *pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  
  39.     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  
  40.     // 转为二值图  
  41.     IplImage *pBinaryImage = cvCreateImage(cvGetSize(pGrayImage), IPL_DEPTH_8U, 1);  
  42.     cvThreshold(pGrayImage, pBinaryImage, 250, 255, CV_THRESH_BINARY);  
  43.   
  44.   
  45.     // 检索轮廓并返回检测到的轮廓的个数  
  46.     CvMemStorage *pcvMStorage = cvCreateMemStorage();  
  47.     CvSeq *pcvSeq = NULL;  
  48.     cvFindContours(pBinaryImage, pcvMStorage, &pcvSeq, sizeof(CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));  
  49.       
  50.     // 画轮廓图  
  51.     IplImage *pOutlineImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3);  
  52.     int nLevels = 5;  
  53.     // 填充成白色  
  54.     cvRectangle(pOutlineImage, cvPoint(0, 0), cvPoint(pOutlineImage->width, pOutlineImage->height), CV_RGB(255, 255, 255), CV_FILLED);  
  55.     cvDrawContours(pOutlineImage, pcvSeq, CV_RGB(255,0,0), CV_RGB(0,255,0), nLevels, 2);  
  56.     // 显示轮廓图  
  57.     cvNamedWindow(pstrWindowsOutLineTitle, CV_WINDOW_AUTOSIZE);  
  58.     cvShowImage(pstrWindowsOutLineTitle, pOutlineImage);  
  59.   
  60.   
  61.     cvWaitKey(0);  
  62.   
  63.     cvReleaseMemStorage(&pcvMStorage);  
  64.   
  65.     cvDestroyWindow(pstrWindowsSrcTitle);  
  66.     cvDestroyWindow(pstrWindowsOutLineTitle);  
  67.     cvReleaseImage(&pSrcImage);  
  68.     cvReleaseImage(&pGrayImage);  
  69.     cvReleaseImage(&pBinaryImage);  
  70.     cvReleaseImage(&pOutlineImage);  
  71.     return 0;  
  72. }  
2019-04-11 13:43:00 qq_35789421 阅读数 103

图像中目标物体的形状检测是图像识别中重要的技术之一,对物体进行检测并提取首先需要做的就是提取物体的轮廓信息,然后再通过轮廓点集特征选择相应的算法进行处理,最后可得到物体的形状信息。轮廓形状是我们看到物体最开始的印象,轮廓提取的原理是通过对原图像进行二值化,利用边缘点连接的层次差别,提取位于数结构特征高的区域点集构成的集合,这部分最可能是物体的轮廓。

OpenCV中提供了函数findContours()用于对物体轮廓进行检测,findContours相关参数的含义:

void findContours(InputArray image,OutputArrayOfArrays contours,OutputArray hierarchy,int mode,int method,Point offsetPoint())

参数image为输入图像,8位单通道二值图像;contours为检测到的轮廓,每个轮廓都在向量中;参数hierarchy为包含图像拓扑结构的信息;mode为可选获取轮廓的方法,常用参数为外轮廓CV_PETR_EXTERNAL,CV_PETR_LIST为检测所有轮廓的不包含继承关系,CV_RETR_TREE为检测所有轮廓的包含继承关系,CV_PETR_CCOMP为检测所有轮廓,但是仅仅建立两层包含关系;method为轮廓近似的方法,参数设置为CV_CHAIN_APPROX_NONE表示把轮廓上所有的点存储,CV_CHAIN_APPROX_SIMPLE表示只存储水平、垂直即对角直线的起始点;offest为可选的偏移量。

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

Mat srcImage;
Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);

void thresh_callback(int,void*)
{
    Mat caany_output;
    vector<vector<point>> contours;
    vector<Vec4i> hierarchy;
    Canny(src_gray,caany_output,thresh,thresh*2,3);          
 findContours(caany_output,contours,hierarchy,CV_PETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
    Mat drawing = Mat::zeros(caany_output.size(),CV_8UC3);
    for(int i = 0;i<contours.size();i++)
    {
        Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
        drawContours(drwing,contours,i,color,2,8,hierarchy,0,Point());
    }
    namedWindow("contours",CV_WINDOW_AUTOSIZE);
    imshow("contours",drawing);
}

int main()
{
    Mat srcImage = imread();
    cvtcolor(srcImage,src_gray,CV_BGR2GRAY);
    blur(src_gray,src_gray,Size(3,3));
    char* source_window = "srcImage";
    namedWindow(source_window,CV_WINDOW_AUTOSIZE);
    imshow(source_window,srcImage);
    createTrackbar("threth:","srcImage",&thresh,max_thresh,thresh_callback);
    thresh_callback(0,0);
    waitkey(0);
    return 0 ;
}

 

2019-07-26 23:07:04 weixin_30768661 阅读数 9

    图像轮廓单一像素化是许多图像处理中必不可少的一步,现在主流的方法都是基于旋转的。今天早上在床上躺了很久,我个人觉得单一像素化其实可以用动态规划结合欧几里德距离来解决的。

   思想如下:

   对于多个像素组成的边界,行逐一增加,对于每一元素计算当前的欧式距离之和并标记访问。不断向前计算,如果遇到了断点,就是不连续的情况,可以考虑跨行,这时要做个标记。

   起点,最好选取该行单一像素点,多个像素点的化选取任意一个也可以的。
   最终获得的最短路径的点集合像素值为1,其它的为0. 对于断点的话,要修正跨行路径,因为欧几里德距离只与相对距离有关,它没考虑离散的路径的具体走向。

   这个问题是否可行,得看下具体的实现情况,五一没时间了。以后有时间的话我得实现下。

转载于:https://www.cnblogs.com/ChenxofHit/archive/2011/05/01/2033786.html

2013-11-06 11:22:06 chenyu19880302 阅读数 1312

一、原理

(1)最常用到的轮廓匹配就是字符的匹配,而两个轮廓最最简洁的方式就是比较它们的轮廓矩。

矩就是通过对轮廓上所有点进行积分运算活求和运算而得到一个粗略的特征,对一幅图像I(x,y)

求普通矩公式为:

                                             

其中p对应x维度上的矩,q对应y维度上的矩,阶数表示对应的部分的指数,该计算是对轮廓边界上

所有像素(数目为n)进行求和。

各阶矩的物理意义:0阶矩(m00)表示目标区域的质量,m00实际上对应轮廓边界上点的数目。

                                   1阶矩(m01,m10)表示目标区域质心

                                    2阶矩(m02,m20,m11)表示旋转半径

                                   3阶矩(m03,m30,m12,m21,)表示描述目标的方位和斜度,反应目标的扭曲程度

但矩要能够作为一种特征描述方法得到应用,其要与目标空间变换(平移、尺度、旋转)无关。因此在几何

矩的基本定义基础上,进一步构造平移不变。尺度不变和旋转不变矩。

(2)中心矩:构造平移不变性

质心坐标为:

                                            

为了使矩具有平移不变性,利用质心坐标构造中心矩:

                                                                                                 

(3)归一化中心矩;构造尺度不变性。为抵消尺度变化对中心矩的影响,用零阶中心矩u00对其余各个中心矩

进行归一化处理,得到归一化中心矩为:

                                                                         

其中r=(p+q)/2+1。

(4)hu矩:构造旋转不变性.hu矩是归一化中心矩的线性组合。hu矩是从中心矩中计算得到,其计算公式如下:

 

根据公式可以看到,每个图像对应7个hu矩。通过观察可以发现当阶数变高时,hu矩一般会变小。根据定义,高阶hu矩

由多个归一化矩的高阶幂计算得到,而归一化矩都是小于1的,所以指数越大,计算所得的值越小。

很自然,使用hu矩就可以比较两个物体判断他们的相似性。


2019-06-28 15:12:00 weixin_30419799 阅读数 29

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法,所以边缘提取的阈值选定会影响最终轮廓发现结果。

python实现

import cv2
import numpy as np


__author__ = "boboa"


def contours_demo(image):
    dst = cv2.GaussianBlur(image, (3, 3), 0)
    gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    cv2.imshow("binary image", thresh)
    # 得到修改后的图像,轮廓,轮廓的层次
    cloneimage, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    """
    cv2.findContours(image, mode, method, contours, hierarchy, offset)
        参数:
            1 要寻找轮廓的图像 只能传入二值图像,不是灰度图像
            2 轮廓的检索模式,有四种:
                cv2.RETR_EXTERNAL表示只检测外轮廓
                cv2.RETR_LIST检测的轮廓不建立等级关系
                cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层
                cv2.RETR_TREE建立一个等级树结构的轮廓
            3 轮廓的近似办法
                cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
                cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
        返回值:
            contours:一个列表,每一项都是一个轮廓,不会存储轮廓所有的点,只存储能描述轮廓的点
            hierarchy:一个ndarray, 元素数量和轮廓数量一样, 
                每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],
                分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数
    """
    for i, contour in enumerate(contours):
        # 绘制轮廓
        cv2.drawContours(image, contours, i, (0, 0, 255), 2)
        """
        # 函数cv2.drawContours(image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel, offset)
        # 第一个参数是一张图片,可以是原图或者其他。
        # 第二个参数是轮廓,也可以说是cv2.findContours()找出来的点集,一个列表。
        # 第三个参数是对轮廓(第二个参数)的索引,当需要绘制独立轮廓时很有用,若要全部绘制可设为-1。
        # 接下来的参数是轮廓的颜色和厚度
        """
        print(i)
    cv2.imshow("detect contours", image)


if __name__ == "__main__":
    img = cv2.imread("image/circles.jpg")
    cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
    cv2.imshow("input image", img)
    contours_demo(img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

二值化图像和检测到的轮廓如下图

 

转载于:https://www.cnblogs.com/qianxia/p/11102800.html

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