[转]图片中的字符分割提取(基于opencv)
2016-07-10 11:06
477 查看
http://blog.csdn.net/anqing715/article/details/16883863
源图片
像这些图片的字符就比较好操作,每个字符都独立,不连在一起,所以轮廓检测最好了。
所以就有:
1.源图片转成单通道的灰阶图片
2.对灰度图像进行阈值操作得到二值图像
(对于一些手机拍的,背景色不是纯的话,可以用cvSmooth()平滑一下。)
二值化后的图片
3.轮廓检测(只获取最外层的)
4.遍历所有检测到的轮廓,用cvBoundingRect()得到每一个轮廓的外接矩形
找到的轮廓
5.抠它们出来,这步在上面的遍历中直接通过setROI方法进行提取。
最后的结果
下面是源码:
[cpp] view plain copy
print?
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
int main(int argc, char* argv[])
{
IplImage* imgSrc = cvLoadImage("D:\\4.jpg",CV_LOAD_IMAGE_COLOR);
IplImage* img_gray = cvCreateImage(cvGetSize(imgSrc), IPL_DEPTH_8U, 1);
cvCvtColor(imgSrc, img_gray, CV_BGR2GRAY);
cvThreshold(img_gray, img_gray,100, 255,CV_THRESH_BINARY_INV);// CV_THRESH_BINARY_INV使得背景为黑色,字符为白色,这样找到的最外层才是字符的最外层
cvShowImage("ThresholdImg",img_gray);
CvSeq* contours = NULL;
CvMemStorage* storage = cvCreateMemStorage(0);
// 上面源图片有瑕疵可以用腐蚀,膨胀来祛除
int count = cvFindContours(img_gray, storage, &contours,sizeof(CvContour),CV_RETR_EXTERNAL);
printf("轮廓个数:%d",count);
int idx = 0;
char szName[56] = {0};
int tempCount=0;
for (CvSeq* c = contours; c != NULL; c = c->h_next) {
CvRect rc =cvBoundingRect(c,0);
// if ()
// {
// continue; 这里可以根据轮廓的大小进行筛选
// }
cvDrawRect(imgSrc, cvPoint(rc.x, rc.y), cvPoint(rc.x + rc.width, rc.y + rc.height), CV_RGB(255, 0, 0));
IplImage* imgNo = cvCreateImage(cvSize(rc.width, rc.height), IPL_DEPTH_8U, 3);
cvSetImageROI(imgSrc, rc);
cvCopyImage(imgSrc, imgNo);
cvResetImageROI(imgSrc);
sprintf(szName, "wnd_%d", idx++);
cvNamedWindow(szName);
cvShowImage(szName, imgNo); //如果想切割出来的图像从左到右排序,或从上到下,可以比较rc.x,rc.y;
cvReleaseImage(&imgNo);
}
cvNamedWindow("src");
cvShowImage("src", imgSrc);
cvWaitKey(0);
cvReleaseMemStorage(&storage);
cvReleaseImage(&imgSrc);
cvReleaseImage(&img_gray);
cvDestroyAllWindows();
return 0;
}
源图片
像这些图片的字符就比较好操作,每个字符都独立,不连在一起,所以轮廓检测最好了。
所以就有:
1.源图片转成单通道的灰阶图片
2.对灰度图像进行阈值操作得到二值图像
(对于一些手机拍的,背景色不是纯的话,可以用cvSmooth()平滑一下。)
二值化后的图片
3.轮廓检测(只获取最外层的)
4.遍历所有检测到的轮廓,用cvBoundingRect()得到每一个轮廓的外接矩形
找到的轮廓
5.抠它们出来,这步在上面的遍历中直接通过setROI方法进行提取。
最后的结果
下面是源码:
[cpp] view plain copy
print?
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
int main(int argc, char* argv[])
{
IplImage* imgSrc = cvLoadImage("D:\\4.jpg",CV_LOAD_IMAGE_COLOR);
IplImage* img_gray = cvCreateImage(cvGetSize(imgSrc), IPL_DEPTH_8U, 1);
cvCvtColor(imgSrc, img_gray, CV_BGR2GRAY);
cvThreshold(img_gray, img_gray,100, 255,CV_THRESH_BINARY_INV);// CV_THRESH_BINARY_INV使得背景为黑色,字符为白色,这样找到的最外层才是字符的最外层
cvShowImage("ThresholdImg",img_gray);
CvSeq* contours = NULL;
CvMemStorage* storage = cvCreateMemStorage(0);
// 上面源图片有瑕疵可以用腐蚀,膨胀来祛除
int count = cvFindContours(img_gray, storage, &contours,sizeof(CvContour),CV_RETR_EXTERNAL);
printf("轮廓个数:%d",count);
int idx = 0;
char szName[56] = {0};
int tempCount=0;
for (CvSeq* c = contours; c != NULL; c = c->h_next) {
CvRect rc =cvBoundingRect(c,0);
// if ()
// {
// continue; 这里可以根据轮廓的大小进行筛选
// }
cvDrawRect(imgSrc, cvPoint(rc.x, rc.y), cvPoint(rc.x + rc.width, rc.y + rc.height), CV_RGB(255, 0, 0));
IplImage* imgNo = cvCreateImage(cvSize(rc.width, rc.height), IPL_DEPTH_8U, 3);
cvSetImageROI(imgSrc, rc);
cvCopyImage(imgSrc, imgNo);
cvResetImageROI(imgSrc);
sprintf(szName, "wnd_%d", idx++);
cvNamedWindow(szName);
cvShowImage(szName, imgNo); //如果想切割出来的图像从左到右排序,或从上到下,可以比较rc.x,rc.y;
cvReleaseImage(&imgNo);
}
cvNamedWindow("src");
cvShowImage("src", imgSrc);
cvWaitKey(0);
cvReleaseMemStorage(&storage);
cvReleaseImage(&imgSrc);
cvReleaseImage(&img_gray);
cvDestroyAllWindows();
return 0;
}
相关文章推荐
- Centos下安装jdk
- tomcat学习(-)windows 7 x64 配置tomcat服务
- Hadoop学习笔记:(一)WordCount运行
- Linux(CentOS)挂载U盘、移动硬盘以及文件拷贝、备份
- 图解Linux命令之--file命令
- Part0:认识重构
- linux more命令简单使用
- Linux下的tar压缩解压缩命令详解
- Linux守护进程加上发送信号固定模式
- Linux学习----vim编辑器
- Docker镜像和仓库笔记
- linux启动mysql
- Java千百问_02基本使用(013)_linux系统如何管理环境变量
- apache日志类型及作用
- linux关于readlink函数获取运行路径的小程序
- linux xfs和ext4的区别
- 图解Linux命令之--cmp命令
- Linux命令(004) -- watch
- 初玩OpenWRT
- opengl 笔记(1)