基于Opencv的数字图像分割算法

基于Opencv的数字图像分割算法

本文主要介绍了一种使用opencv库来对一串连续数字的分割和存储,其中主要运用了灰度化,局部二值化,纵向和横向投影法。

首先对图片进行滤波,开运算和局部二值化,得到二值化图如下:

在这里插入图片描述
在这里插入图片描述

利用横向投影求和,确定出数字的上边界和下边界,并将图片截取出来:

在这里插入图片描述

利用纵向投影求和,确定出每个数字的左右边界,并利用容器将每个数字的左右边界存储起来,最终确定出每个数字和新建图坐标之间的对应关系将图截取出来:

在这里插入图片描述

代码如下(传入灰度图):

bool contour(Mat image) {
	Mat img_gau, img_open, img_seg, img_edge;
	// 高斯模糊
	GaussianBlur(image, img_gau, Size(7, 7), 0, 0);
	//imshow("绘制方框", image);
	 开运算
	Mat element = getStructuringElement(MORPH_RECT, Size(image.rows, image.cols));
	morphologyEx(img_gau, img_open, MORPH_OPEN, element);
	addWeighted(img_gau, 1, img_open, -1, 0, img_open);
	// 阈值分割
	//threshold(img_open, img_seg, 20, 255, THRESH_BINARY_INV);
	adaptiveThreshold(img_open, img_seg, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 10);
	imshow("1", img_seg);
	int row_dst = img_seg.rows;
	int col_dst = img_seg.cols;
	int mid_sp = 0,mid_cz=0;
	vector<int> mid_sph,mid_czh;
	for (int i = 0; i < row_dst; i++)
	{
		  for (int j = 0; j < col_dst; j++)
		  {
			  mid_sp = mid_sp + img_seg.at<uchar>(i, j);
		  }

			  cout << "第" << i + 1 << "行的水平投影为:" << mid_sp << endl;//144000
			  mid_sph.push_back(mid_sp);
			  mid_sp = 0;
	}
	int sp1=0, sp2=0;
	for (int i = 0; i < mid_sph.size(); i++)
	{
		 if (mid_sph[i] != 0 && sp1 == 0)
		 {
			 sp1 = i;
		 }
		 else if(mid_sph[i] == 0 && sp1 != 0){
			  sp2 = i;
			  break;
		 }
	}
	int spc;
	spc = abs(sp1 - sp2);
	Mat new_sp_img = Mat::zeros(Size(500,spc),CV_8UC1);
	for (int i = 0; i < new_sp_img.rows; i++) {
		 for (int j = 0; j < new_sp_img.cols;j++) {
			new_sp_img.at<uchar>(i, j) = img_seg.at<uchar>(i+ sp1, j);
		 }
	}
	imshow("ll", new_sp_img);
	for (int i = 0; i < col_dst; i++)
	{
		 for (int j = 0; j < row_dst; j++)
		 {
			mid_cz = mid_cz + img_seg.at<uchar>(j, i);
		 }

		   cout << "第" << i + 1 << "列的垂直投影为:" << mid_cz << endl;//144000
		   mid_czh.push_back(mid_cz);
		   mid_cz = 0;
	  }

	  vector<Vec2i> czd;
	  int cz1 = 0, cz2 = 0;
	  for (int i = 0; i < mid_czh.size(); i++)
	  {
		   if (mid_czh[i] != 0 && cz1 == 0)
		   {
				cz1 = i;
		   }
		   else if (mid_czh[i] == 0 && cz1 != 0) {
				cz2 = i;
				czd.push_back(Vec2i(cz1,cz2));
				cz1 = 0;
		   }
	  }
	  Mat new_cz_img = Mat::zeros(Size(spc, spc), CV_8UC1);
	  int czd_zs = 0;
	  //new_sp_img
	  for (int i = 0; i < czd.size(); i++) {
	   int sub_cz = (spc-abs(czd[i][0] - czd[i][1]))/2; 
		   for (int j = 0; j < spc; j++) {
				czd_zs = czd[i][0];
				for (int k = 0; k < spc; k++) { 
					 if(k< sub_cz)
					 {
					  new_cz_img.at<uchar>(j, k) = 0;
					 }
					 else if (czd_zs <= czd[i][1]) {
					  new_cz_img.at<uchar>(j, k) = new_sp_img.at<uchar>(j, czd_zs++);
					 }
					 else
					 {
					  new_cz_img.at<uchar>(j, k) = 0;
					 }
			}
	   }
		   Mat final_cc;
		   resize(new_cz_img, final_cc, Size(28, 28));
		   imwrite("number" + to_string(i) + ".jpg", final_cc);
		   imshow("number" + to_string(i), final_cc);
	  }
  
	  imshow("绘制方框", img_seg);for (int i = 0; i < col_dst; i++)
	{
		 for (int j = 0; j < row_dst; j++)
		 {
			mid_cz = mid_cz + img_seg.at<uchar>(j, i);
		 }

		   cout << "第" << i + 1 << "列的垂直投影为:" << mid_cz << endl;//144000
		   mid_czh.push_back(mid_cz);
		   mid_cz = 0;
	  }

	  vector<Vec2i> czd;
	  int cz1 = 0, cz2 = 0;
	  for (int i = 0; i < mid_czh.size(); i++)
	  {
		   if (mid_czh[i] != 0 && cz1 == 0)
		   {
				cz1 = i;
		   }
		   else if (mid_czh[i] == 0 && cz1 != 0) {
				cz2 = i;
				czd.push_back(Vec2i(cz1,cz2));
				cz1 = 0;
		   }
	  }
	  Mat new_cz_img = Mat::zeros(Size(spc, spc), CV_8UC1);
	  int czd_zs = 0;
	  //new_sp_img
	  for (int i = 0; i < czd.size(); i++) {
	   int sub_cz = (spc-abs(czd[i][0] - czd[i][1]))/2; 
		   for (int j = 0; j < spc; j++) {
				czd_zs = czd[i][0];
				for (int k = 0; k < spc; k++) { 
					 if(k< sub_cz)
					 {
					  new_cz_img.at<uchar>(j, k) = 0;
					 }
					 else if (czd_zs <= czd[i][1]) {
					  new_cz_img.at<uchar>(j, k) = new_sp_img.at<uchar>(j, czd_zs++);
					 }
					 else
					 {
					  new_cz_img.at<uchar>(j, k) = 0;
					 }
			}
	   }
		   imwrite("number" + to_string(i) + ".jpg", final_cc);
		   imshow("number" + to_string(i), final_cc);
	  }
	waitKey(0);
	 return true;
	}

感谢学姐的大力支持和帮助!

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、实验内容 本实验使用数字图像处理的基本方法,构建了一个车道线检测模型。该模型可以识别图像中所有的车道线,并得到完整的车道线信息。模型在tuSimple Lane Dataset大小为100的数据子集进行了测试,达到了较好的结果。 2、实现思路 实现车道线检测,主要包含两部分操作 1. 道路图像的处理,主要包括灰度图转换、基于高斯平滑的图像去噪、基于Canny算法的边缘提取 2. 车道线检测方法,主要包括获取感兴趣区域(ROI)、形态学闭运算、基于Hough变换的直线检测 模型的处理流程如下, <img src="./result/image_of_readme/img.png" alt="image-20210214120515919" style="zoom:80%;" /> # 2.1 道路图像处理 通过对道路图像进行处理,突出图像中的车道线部分。模型将彩色图像转化成灰度图像进行处理,目的是简化模型的复杂度,提高运行效率。 ## 2.1.1 高斯平滑 由于光照、路面情况、拍摄质量等问题,道路图像上存在很多噪声,通过高斯滤波使图像变得平滑,减弱图像中的噪声对结果的影响,提高车道线检测模型的鲁棒性。 高斯平滑就是使用高斯滤波器与原图像进行卷积,得到平滑图像。与均值滤波类似,它们都是取滤波器窗口内像素的加权均值作为输出。高斯滤波器的权值分布满足二维高斯函数 一开始选择的更新聚类中心的方法,是取同一类别的平均值,效果不佳。经过尝试最后采用取每个类别的初始值为中心点,实现较好的效果。示例如下: ![聚类方法对比](./result/image_of_readme/update_cmp.png) 评测结果对比: | 中心点 | Accuracy | FP | FN | | ---------- | -------- | ------ | ------ | | 数据均值 | 0.5740 | 0.7058 | 0.7533 | | 聚类初始值 | 0.7539 | 0.5025 | 0.5242 | 分析原因:由于车道线有一定弧度,导致前半部分和后半部分的车道线参数差距较大。如果降低判定相似的标准,就会导致本不相似的直线求均值,从而使Accuracy较低;如果提高相似的标准就会,导致聚类得到类别很多,从而FP较大;因此采用加权均值更新聚类中心点并不理想。 按照车道线聚类结果中每个类别的大小,对聚类结果进行排序,选择所有聚类结果中规模最大的4个类作为最终确定的直线参数。 实验总结及改进 实验过程中尝试了很多方案,如采用形态学运算,提高车道线的完整性;通过阈值分割,去除背景和干扰物;采用均值作为聚类中心等。由于方案设计上的主观缺陷和检测任务的存在的光照不均、环境复杂等客观因素,以上方案均被舍弃。最终经过实践得到了一种鲁棒性较好,效果较优的车道线检测方案。 通过查阅相关资料,我了解到更多车道线检测的改进算法,例如可以通过最大类间方差法(OTSU)进行阈值分割、动态ROI区域等。可以通过以上算法进一步提高模型精度和性能。 运行方法 1. **编译**(Windows 10): * cmake version 3.19.3 * GNU Make version 4.2.1 * OpenCV version 4.5.1 在 powershell 中执行以下命令: (1)生成 debug 版本: ```shell mkdir debug # 创建编译目录 cd debug cmake -G "MinGW Makefiles" .. # 生成 Makefile mingw32-make # 使用 MinGW 编译代码 ``` (2)生成 release 版本 ```shell mkdir release cd release cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release .. mingw32-make ``` 2. **运行** > 在 debug / release 目录中双击 lane_detection.exe 即可运行 3. **测评** ```shell cd .. python evaluate.py ./result/predict.json ./data/groundtruth.json ```
处理数字图像是Python中常见的任务之一。你可以使用Python中的许多库和框架来进行数字图像处理,例如OpenCV、Pillow、SciPy等。 以下是你可以使用Python对数字图像进行处理的一些基本步骤: 1. 导入图像:使用Python中的库来读取和导入图像文件,例如OpenCV或Pillow库。例如,使用Pillow库来导入图像: ```python from PIL import Image img = Image.open('image.jpg') # 导入图像 ``` 2. 转换图像格式:使用Python库来将图像转换为所需的格式。例如,使用OpenCV库将图像转换为灰度格式: ```python import cv2 gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图像转换为灰度格式 ``` 3. 图像增强:使用Python库来增强图像的质量,例如调整亮度、对比度等。例如,使用Pillow库来增加图像亮度: ```python from PIL import ImageEnhance enhancer = ImageEnhance.Brightness(img) bright_img = enhancer.enhance(1.5) # 将图像亮度增加1.5倍 ``` 4. 图像滤波:使用Python库来对图像进行滤波操作,例如平滑、边缘检测等。例如,使用OpenCV库进行高斯滤波: ```python blur_img = cv2.GaussianBlur(img, (5,5), 0) # 进行高斯滤波 ``` 5. 图像分割:使用Python库来将图像分割为不同的区域或对象。例如,使用OpenCV库进行图像分割: ```python ret, thresh_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY) # 进行二值化图像分割 ``` 6. 特征提取:使用Python库来提取图像中的特征,例如边缘、角点等。例如,使用OpenCV库进行边缘检测: ```python edges = cv2.Canny(gray_img, 100, 200) # 进行边缘检测 ``` 这些步骤只是数字图像处理的基础,你可以根据你的需求和任务来选择适当的库和算法来处理数字图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值