目录
1.Iplmage版提取连通区域坐标
#include <iostream>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
using namespace std;
int main()
{
CvMemStorage *storage = cvCreateMemStorage(0); // 内存存储序列
IplImage *img = cvLoadImage("E:\\study_opencv_video\\lesson14_1\\Debug\\55.png", 0);
IplImage *imgColor = cvCreateImage(cvGetSize(img), 8, 3);
IplImage *contoursImage = cvCreateImage(cvGetSize(img), 8, 1);
CvSeq *contours = 0, *contoursTemp = 0;
cvZero(contoursImage);
cvThreshold(img, img, 100, 255, CV_THRESH_BINARY); // 二值化操作
cvCvtColor(img, imgColor, CV_GRAY2BGR);
int totals = cvFindContours(img, storage,&contours, sizeof(CvContour), //img必须是一个二值图像 storage 用来存储的contours指向存储的第一个轮廓
CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
contoursTemp = contours;
int count = 0;
int i;
for(;contoursTemp != 0; contoursTemp = contoursTemp -> h_next) /// 这样可以访问每一个轮廓 ====横向轮廓
{
for(i = 0; i < contoursTemp -> total; i++) // 提取一个轮廓的所有坐标点
{
CvPoint *pt = (CvPoint*) cvGetSeqElem(contoursTemp, i); // 得到一个轮廓中一个点的函数cvGetSeqElem
cvSetReal2D(contoursImage, pt->y, pt->x, 255.0);
cvSet2D(imgColor, pt->y, pt->x, cvScalar(0,0,255,0));
}
count ++;
CvSeq *InterCon = contoursTemp->v_next; // 访问每个轮廓的纵向轮廓
for(; InterCon != 0; InterCon = InterCon ->h_next)
{
for(i = 0; i < InterCon->total; i++ )
{
CvPoint *pt = (CvPoint*)cvGetSeqElem(InterCon, i);
cvSetReal2D(contoursImage, pt->y, pt->x, 255.0);
cvSet2D(imgColor, pt->y, pt->x, cvScalar(0, 255, 0, 0));
}
}
}
cvNamedWindow("contoursImage");
cvShowImage("contoursImage", contoursImage);
cvNamedWindow("imgColor");
cvShowImage("imgColor",imgColor);
cvWaitKey(0);
cvReleaseMemStorage(&storage); // 也要释放内存序列空间
cvReleaseImage(&contoursImage);
cvReleaseImage(&imgColor);
cvDestroyWindow("contoursImage");
cvDestroyWindow("imgColor");
return 0;
}
2.Mat版提取连通区域坐标,仅保留最大连通区域
Mat findMaxContours(Mat src)
{
Mat bw; src.copyTo(bw);
//查找最大连通区域
vector<vector<Point>>contours; //每个轮廓中的点
vector<Vec4i>hierarchy; //轮廓的索引
findContours(bw, contours, hierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
double max_area = 0;
int index = 0;
for (int i = 0; i < contours.size(); i++)
{
if (contourArea(contours[i]) > max_area)
{
max_area = contourArea(contours[i]);
index = i;
}
}
Mat dstImage = Mat::zeros(src.rows, src.cols, CV_8UC1);
if (contours.size()>0)
{
drawContours(dstImage, contours, index, Scalar(255), -1);
}
contours.clear();
hierarchy.clear();
contours.swap(vector<vector<Point>>(contours));
hierarchy.swap(vector<Vec4i>(hierarchy));
return dstImage;
//RotatedRect rect_Pointer = minAreaRect(contours[index]);
//cv::Point2f* vertices = new cv::Point2f[4];
//rect_Pointer.points(vertices);
//std::vector<cv::Point> contourRect;
//for (int i = 0; i < 4; i++)
//{
// contourRect.push_back(vertices[i]);
//}
//std::vector<std::vector<cv::Point>> contourRects;
//contourRects.push_back(contourRect);
//drawContours(dstImage, contourRects, 0, Scalar(255), -1);
}
3.标记连通区域并计算连通区域特性
//ref:https://blog.csdn.net/fei13148687/article/details/104800400
int cv::connectedComponents(
InputArray image, // 输入二值图像
OutputArray labels, // 输出的标记图像,背景index=0
int connectivity = 8, // 连通域,默认是8连通
int ltype = CV_32S // 输出的labels类型,默认是CV_32S
)
//带有统计信息的API:
int cv::connectedComponentsWithStats(
InputArray image, // 输入二值图像
OutputArray labels, // 输出的标记图像,背景index=0
OutputArray stats, // 统计信息,包括每个组件的位置、宽、高与面积
OutputArray centroids, // 每个组件的中心位置坐标cx, cy
int connectivity, // 连通域,默认是8连通
int ltype, // 输出的labels类型,默认是CV_32S
int ccltype // 连通组件算法
)
4.Mat与IplImage转换
//--Mat to IplImage
Mat src = Mat::zeros(10, 10, CV_8UC1);
IplImage* srcIpl = NULL;
srcIpl = &(IplImage)src;//Ipl与Mat共享内存,Release尽量两个变量都手动释放
//--IplImage to Mat
Mat srcMat(srcIpl , false);//仅创建Mat头与IplImage共享内存