iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >OpenCV图像轮廓提取的实现
  • 847
分享到

OpenCV图像轮廓提取的实现

OpenCV图像轮廓提取OpenCV轮廓提取 2022-11-13 14:11:53 847人浏览 泡泡鱼
摘要

目录前言提取傅里叶变换的高频信息通过蚁群算法进行图片轮廓提取Canny边缘检测  使用cuda加速提取轮廓前言 常用的轮廓提取算法有:Canny、阈值分割、提取傅

前言

常用的轮廓提取算法有:Canny、阈值分割、提取傅里叶变换的高频信息,还有别具一格的蚁群算法,当然比较常见的作法是使用阈值分割+边缘查找,在OpenCV里是threshold和findContours两个函数的组合使用,和Canny。

轮廓提取的算法很多,而其目的都是为了找到图像中灰阶差比较大的位置。而所谓亚像素提取,则是使用了插值算法,以找出灰阶差最大的位置。

提取傅里叶变换的高频信息

##############
#图像中的轮廓提取
#时间:2019/1/3
#作者:cclplus
#仅供学习交流使用
#如有疑问或者需求,可以联系作者的邮箱
#如果你有什么好的建议或者指导,我将不胜感激


import cv2
import numpy as np
from matplotlib import pyplot as plt
import copy
img = cv2.imread('liuyifei.jpg',0)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

rows,cols = img.shape
crow,ccol = int(rows/2) , int(cols/2)
for i in range(crow-30,crow+30):
    for j in range(ccol-30,ccol+30):
        fshift[i][j]=0.0
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)#进行高通滤波
# 取绝对值
img_back = np.abs(img_back)
plt.subplot(121),plt.imshow(img,cmap = 'gray')#因图像格式问题,暂已灰度输出
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
#先对灰度图像进行伽马变换,以提升暗部细节
rows,cols = img_back.shape
gamma=copy.deepcopy(img_back)
rows=img.shape[0]
cols=img.shape[1]
for i in range(rows):
    for j in range(cols):
        gamma[i][j]=5.0*pow(gamma[i][j],0.34)#0.34这个参数是我手动调出来的,根据不同的图片,可以选择不同的数值
#对灰度图像进行反转

for i in range(rows):
    for j in range(cols):
        gamma[i][j]=255-gamma[i][j]
plt.subplot(122),plt.imshow(gamma,cmap = 'gray')
plt.title('Result in HPF'), plt.xticks([]), plt.yticks([])
plt.show()

原图

在这里插入图片描述

输出结果

在这里插入图片描述

通过蚁群算法进行图片轮廓提取

相关代码我上传到了我的GitHub
https://github.com/YuruTu/Ant_colony

在这里插入图片描述

效果不够理想,这也算得上蚁群算法的一大特点,对参数要求较高,需要调参。相关内容,笔者会持续更新

Canny边缘检测  

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('liuyifei.jpg',0)
edges = cv2.Canny(img,100,200)

plt.subplot(121),plt.imshow(img,cmap='gray')
plt.title('original'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap='gray')
plt.title('edge'),plt.xticks([]),plt.yticks([])

plt.show()

在这里插入图片描述

使用cuda加速提取轮廓

#include <iOStream>
#include <cuda.h>
#include <cstdlib>
#include <stdio.h>
#include <cuda_runtime.h>
#include <string>
#include <assert.h>
#include <cuda_runtime.h>
#include <cuda_runtime_api.h>
#include <device_launch_parameters.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;
// GPU constant memory to hold our kernels (extremely fast access time)
__constant__ float convolutionKernelStore[256];


__global__ void convolve(unsigned char *source, int width, int height, int paddingX, int paddingY, unsigned int kOffset, int kWidth, int kHeight, unsigned char *destination)
{
	// Calculate our pixel's location
	int x = (blockIdx.x * blockDim.x) + threadIdx.x;
	int y = (blockIdx.y * blockDim.y) + threadIdx.y;

	float sum = 0.0;
	int   pWidth = kWidth / 2;
	int   pHeight = kHeight / 2;

	//Solo ejecuta validos pixeles
	if (x >= pWidth + paddingX && y >= pHeight + paddingY && x < (blockDim.x * gridDim.x) - pWidth - paddingX &&
		y < (blockDim.y * gridDim.y) - pHeight - paddingY)
	{
		for (int j = -pHeight; j <= pHeight; j++)
		{
			for (int i = -pWidth; i <= pWidth; i++)
			{
				// Sample the weight for this location
				int ki = (i + pWidth);
				int kj = (j + pHeight);
				float w = convolutionKernelStore[(kj * kWidth) + ki + kOffset];


				sum += w * float(source[((y + j) * width) + (x + i)]);
			}
		}
	}

	// Promedio sum
	destination[(y * width) + x] = (unsigned char)sum;
}

__global__ void pythaGoras(unsigned char *a, unsigned char *b, unsigned char *c)
{
	int idx = (blockIdx.x * blockDim.x) + threadIdx.x;

	float af = float(a[idx]);
	float bf = float(b[idx]);

	c[idx] = (unsigned char)sqrtf(af*af + bf * bf);
}

// crea imagen buffer
unsigned char* createImageBuffer(unsigned int bytes, unsigned char **devicePtr)
{
	unsigned char *ptr = NULL;
	cudaSetDeviceFlags(cudaDeviceMapHost);
	cudaHostAlloc(&ptr, bytes, cudaHostAllocMapped);
	cudaHostGetDevicePointer(devicePtr, ptr, 0);
	return ptr;
}


int main(int arGC, char** argv) {
	// Abre la camaraWEB
	cv::VideoCapture camera(0);
	cv::Mat          frame;
	if (!camera.isOpened())
		return -1;

	// capture windows
	cv::namedWindow("Source");
	cv::namedWindow("Greyscale");
	cv::namedWindow("Blurred");
	cv::namedWindow("Sobel");

	// Funciones para obtener el tiempo de ejecucion 
	cudaEvent_t start, stop;
	cudaEventCreate(&start);
	cudaEventCreate(&stop);

	// Crea kernel gaussian(sum = 159)
	const float gaussianKernel5x5[25] =
	{
		2.f / 159.f,  4.f / 159.f,  5.f / 159.f,  4.f / 159.f, 2.f / 159.f,
		4.f / 159.f,  9.f / 159.f, 12.f / 159.f,  9.f / 159.f, 4.f / 159.f,
		5.f / 159.f, 12.f / 159.f, 15.f / 159.f, 12.f / 159.f, 5.f / 159.f,
		4.f / 159.f,  9.f / 159.f, 12.f / 159.f,  9.f / 159.f, 4.f / 159.f,
		2.f / 159.f,  4.f / 159.f,  5.f / 159.f,  4.f / 159.f, 2.f / 159.f,
	};
	cudaMemcpyToSymbol(convolutionKernelStore, gaussianKernel5x5, sizeof(gaussianKernel5x5), 0);
	const unsigned int gaussianKernel5x5Offset = 0;

	// Sobel gradient kernels
	const float sobelGradientX[9] =
	{
		-1.f, 0.f, 1.f,
		-2.f, 0.f, 2.f,
		-1.f, 0.f, 1.f,
	};
	const float sobelGradientY[9] =
	{
		1.f, 2.f, 1.f,
		0.f, 0.f, 0.f,
		-1.f, -2.f, -1.f,
	};
	cudaMemcpyToSymbol(convolutionKernelStore, sobelGradientX, sizeof(sobelGradientX), sizeof(gaussianKernel5x5));
	cudaMemcpyToSymbol(convolutionKernelStore, sobelGradientY, sizeof(sobelGradientY), sizeof(gaussianKernel5x5) + sizeof(sobelGradientX));
	const unsigned int sobelGradientXOffset = sizeof(gaussianKernel5x5) / sizeof(float);
	const unsigned int sobelGradientYOffset = sizeof(sobelGradientX) / sizeof(float) + sobelGradientXOffset;

	// Crea CPU/GPU imagenes compartidos
	camera >> frame;
	unsigned char *sourceDataDevice, *blurredDataDevice, *edgesDataDevice;
	cv::Mat source(frame.size(), CV_8U, createImageBuffer(frame.size().width * frame.size().height, &sourceDataDevice));
	cv::Mat blurred(frame.size(), CV_8U, createImageBuffer(frame.size().width * frame.size().height, &blurredDataDevice));
	cv::Mat edges(frame.size(), CV_8U, createImageBuffer(frame.size().width * frame.size().height, &edgesDataDevice));

	// Crea 2 imagenes temporales (sobel gradients)
	unsigned char *deviceGradientX, *deviceGradientY;
	cudaMalloc(&deviceGradientX, frame.size().width * frame.size().height);
	cudaMalloc(&deviceGradientY, frame.size().width * frame.size().height);

	// Loop while captura imagenes
	while (1)
	{
		// Captura la imagen en eScala de grises
		camera >> frame;
		cvtColor(frame, source, COLOR_RGB2GRAY);
		_sleep(1);
		// Graba el tiempo que demora el proceso
		cudaEventRecord(start);
		{
			// convolution kernel  parametros
			dim3 cblocks(frame.size().width / 16, frame.size().height / 16);
			dim3 cthreads(16, 16);

			// pythagoran kernel parametros
			dim3 pblocks(frame.size().width * frame.size().height / 256);
			dim3 pthreads(256, 1);

			//  gaussian blur (first kernel in store @ 0)
			convolve <<<cblocks, cthreads >> > (sourceDataDevice, frame.size().width, frame.size().height, 0, 0, gaussianKernel5x5Offset, 5, 5, blurredDataDevice);

			// sobel gradient convolutions (x&y padding is now 2 because there is a border of 2 around a 5x5 gaussian filtered image)
			convolve << <cblocks, cthreads >> > (blurredDataDevice, frame.size().width, frame.size().height, 2, 2, sobelGradientXOffset, 3, 3, deviceGradientX);
			convolve << <cblocks, cthreads >> > (blurredDataDevice, frame.size().width, frame.size().height, 2, 2, sobelGradientYOffset, 3, 3, deviceGradientY);
			pythagoras << <pblocks, pthreads >> > (deviceGradientX, deviceGradientY, edgesDataDevice);

			cudaThreadSynchronize();
		}
		cudaEventRecord(stop);

		// Muestra tiempo de ejecucion
		float ms = 0.0f;
		cudaEventSynchronize(stop);
		cudaEventElapsedTime(&ms, start, stop);
		std::cout << "Elapsed GPU time: " << ms << " milliseconds" << std::endl;

		// Muestra resultados
		imshow("Source", frame);
		imshow("Greyscale", source);
		imshow("Blurred", blurred);
		imshow("Sobel", edges);

		// Spin
		if (cv::waiTKEy(1) == 27) break;
	}

	// Exit
	cudaFreeHost(source.data);
	cudaFreeHost(blurred.data);
	cudaFreeHost(edges.data);
	cudaFree(deviceGradientX);
	cudaFree(deviceGradientY);

	return 0;
}

很多时候加上Cuda是有必要的,如果你要使用hough变换之类的时间复杂度比较高的代码,Gpu编程会给你带来多个数量级的加速。

到此这篇关于OpenCV图像轮廓提取的实现的文章就介绍到这了,更多相关OpenCV图像轮廓提取内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: OpenCV图像轮廓提取的实现

本文链接: https://www.lsjlt.com/news/172042.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • OpenCV图像轮廓提取的实现
    目录前言提取傅里叶变换的高频信息通过蚁群算法进行图片轮廓提取Canny边缘检测  使用cuda加速提取轮廓前言 常用的轮廓提取算法有:Canny、阈值分割、提取傅...
    99+
    2022-11-13
    OpenCV图像轮廓提取 OpenCV 轮廓提取
  • Python OpenCV 基于图像边缘提取的轮廓发现函数
    基础知识铺垫 在图像中,轮廓可以简单的理解为连接具有相同颜色的所有连续点(边界)的曲线,轮廓可用于形状分析和对象检测、识别等领域。 轮廓发现的原理:先通过阈值分割提取目标物体,再通过...
    99+
    2022-11-11
  • OpenCV图像轮廓的绘制方法
    本文实例为大家分享了检测几何图形轮廓和检测花朵图形轮廓,供大家参考,具体内容如下 OpenCV绘制图像轮廓 绘制轮廓的一般步骤: 1、读取图像 image = cv2.imrea...
    99+
    2022-11-12
  • opencv实现图形轮廓检测
    要想实现轮廓检测,首先我们需要对待检测的图像进行图像处理: 图像灰度化、高斯滤波、Canny 边缘检测、边缘检测放大处理、提取轮廓。 一、实现简单的全图型检测 即只要将drawCon...
    99+
    2022-11-12
  • Python图像处理之如何实现目标物体轮廓提取
    这篇文章将为大家详细讲解有关Python图像处理之如何实现目标物体轮廓提取,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1 引言目标物体的边缘对图像识别和计算机分析十分有用。边缘可以勾画出目标物体,使观察...
    99+
    2023-06-20
  • Python图像处理之目标物体轮廓提取的实现方法
    目录1 引言2 原理3 Python实现1)读入彩色图像2) 彩色图像灰度化3)二值化4)提取轮廓4 总结1 引言 目标物体的边缘对图像识别和计算机分析十分有用。边缘可以勾画出目标物...
    99+
    2022-11-12
  • 怎么利用Python+OpenCV实现简易图像边缘轮廓检测
    本篇内容主要讲解“怎么利用Python+OpenCV实现简易图像边缘轮廓检测”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么利用Python+OpenCV实现简易图像边缘轮廓检测”吧!函数基础...
    99+
    2023-06-30
  • OpenCV-Python实现轮廓的特征值
    目录前言宽高比ExtendSolidity等效直径方向掩摸和像素点最大值,最小值以及它们的位置平均颜色及平均灰度极点前言 轮廓自身的一些属性特征及轮廓所包围对象的特征对于描述图像具有...
    99+
    2022-11-12
  • Python中OpenCV实现查找轮廓的实例
    本文将结合实例代码,介绍 OpenCV 如何查找轮廓、获取边界框。 代码: contours.py OpenCV 提供了 findContours 函数查找轮廓,需要以二值化图像作为...
    99+
    2022-11-12
  • 如何利用Python+OpenCV实现简易图像边缘轮廓检测(零基础)
    目录前言函数基础与三方库cv.threshold(pic,thresh,maxvalue,model)cv.findContours(待处理图片,model(提取模式),method...
    99+
    2022-11-11
  • python opencv 找出图像中的最大轮廓并填充(生成mask)
    本文主要介绍了python opencv 找出图像中的最大轮廓并填充,分享给大家,具体如下: import cv2 import numpy as np from PIL imp...
    99+
    2022-11-11
  • 怎么在python中使用opencv查找图像中的最大的轮廓
    本篇文章给大家分享的是有关怎么在python中使用opencv查找图像中的最大的轮廓,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。具体如下:import cv2imp...
    99+
    2023-06-09
  • python中opencv图像金字塔轮廓及模板匹配是怎样的
    这篇文章给大家介绍python中opencv图像金字塔轮廓及模板匹配是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1.图像金字塔①高斯金字塔向下采样,数据会越来越少,减少的方式是:将偶数行和列删除向上采样,数据...
    99+
    2023-06-25
  • 怎么在Python中使用OpenCV实现轮廓的特征值
    本篇文章给大家分享的是有关怎么在Python中使用OpenCV实现轮廓的特征值,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。宽高比在轮廓中,我们可以通过宽高比来描述轮廓,例如矩...
    99+
    2023-06-15
  • python中的opencv 图像分割与提取
    目录图像分割与提取用分水岭算法实现图像分割与提取算法原理相关函数介绍分水岭算法图像分割实例交互式前景提取图像分割与提取 图像中将前景对象作为目标图像分割或者提取出来。对背景本身并无兴...
    99+
    2022-11-11
  • Android+OpenCv4实现边缘检测及轮廓绘制出图像最大边缘
    实现步骤: 图像灰度化 边缘检测 根据Canny检测得出来的Mat寻找轮廓 算出最大轮廓周长or面积 根据获取到的最大轮廓下标进行轮廓绘制 ...
    99+
    2022-11-12
  • QT编写地图实现在线轮廓图的示例代码
    目录一、前言二、功能特点三、体验地址四、效果图五、相关代码 一、前言 轮廓图也叫行政区划,这里的轮廓图是指百度地图的区域轮廓图,不是之前文章中提到的echart专用的轮廓图,百度地图...
    99+
    2022-11-12
  • QT编写地图实现离线轮廓图的示例代码
    目录一、前言二、功能特点三、体验地址四、效果图五、相关代码 一、前言 离线轮廓图使用起来,就没有在线轮廓图方便了,在线的可以直接传入名称拿到,离线的只能自己绘制了,一般需要用区域轮廓...
    99+
    2022-11-12
  • OpenCV 图像绘制的实现
    目录+直线绘制圆形绘制矩形绘制椭圆型绘制自定义形状绘制文本+直线绘制 参数解析:(图像矩阵,直线起始坐标, 直线终止坐标、颜色、线条厚度) import cv2 import n...
    99+
    2022-11-12
  • python中的opencv图像分割与提取的方法
    这篇文章主要介绍了python中的opencv图像分割与提取的方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇python中的opencv图像分割与提取的方法文章都会有所收获,下面我们一起来看看吧。图像分割与...
    99+
    2023-06-30
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作