1)Two-pass算法的一种实现
说明:
基于OpenCV和C++实现,领域:4-领域。实现与算法描述稍渣拿孝有差别(具体为记录具有相敏森等关系的label方法实现上)。
// Connected Component Analysis/Labeling By Two-Pass Algorithm
// Author: www.icvpr.com
// Blog : http://blog.csdn.net/icvpr
#include <iostream>
#include <如稿string>
#include <list>
#include <vector>
#include <map>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
void icvprCcaByTwoPass(const cv::Mat&_binImg, cv::Mat&_lableImg)
{
// connected component analysis (4-component)
// use two-pass algorithm
// 1. first pass: label each foreground pixel with a label
// 2. second pass: visit each labeled pixel and merge neighbor labels
//
// foreground pixel: _binImg(x,y) = 1
// background pixel: _binImg(x,y) = 0
if (_binImg.empty() ||
_binImg.type() != CV_8UC1)
{
return
}
// 1. first pass
_lableImg.release()
_binImg.convertTo(_lableImg, CV_32SC1)
int label = 1 // start by 2
std::vector<int>labelSet
labelSet.push_back(0) // background: 0
labelSet.push_back(1) // foreground: 1
int rows = _binImg.rows - 1
int cols = _binImg.cols - 1
for (int i = 1i <rowsi++)
{
int* data_preRow = _lableImg.ptr<int>(i-1)
int* data_curRow = _lableImg.ptr<int>(i)
for (int j = 1j <colsj++)
{
if (data_curRow[j] == 1)
{
std::vector<int>neighborLabels
neighborLabels.reserve(2)
int leftPixel = data_curRow[j-1]
int upPixel = data_preRow[j]
if ( leftPixel >1)
{
neighborLabels.push_back(leftPixel)
}
if (upPixel >1)
{
neighborLabels.push_back(upPixel)
}
if (neighborLabels.empty())
{
labelSet.push_back(++label) // assign to a new label
data_curRow[j] = label
labelSet[label] = label
}
else
{
std::sort(neighborLabels.begin(), neighborLabels.end())
int smallestLabel = neighborLabels[0]
data_curRow[j] = smallestLabel
// save equivalence
for (size_t k = 1k <neighborLabels.size()k++)
{
int tempLabel = neighborLabels[k]
int&oldSmallestLabel = labelSet[tempLabel]
if (oldSmallestLabel >smallestLabel)
{
labelSet[oldSmallestLabel] = smallestLabel
oldSmallestLabel = smallestLabel
}
else if (oldSmallestLabel <smallestLabel)
{
labelSet[smallestLabel] = oldSmallestLabel
}
}
}
}
}
}
// update equivalent labels
// assigned with the smallest label in each equivalent label set
for (size_t i = 2i <labelSet.size()i++)
{
int curLabel = labelSet[i]
int preLabel = labelSet[curLabel]
while (preLabel != curLabel)
{
curLabel = preLabel
preLabel = labelSet[preLabel]
}
labelSet[i] = curLabel
}
// 2. second pass
for (int i = 0i <rowsi++)
{
int* data = _lableImg.ptr<int>(i)
for (int j = 0j <colsj++)
{
int&pixelLabel = data[j]
pixelLabel = labelSet[pixelLabel]
}
}
}
2)Seed-Filling种子填充方法
说明:
基于OpenCV和C++实现;领域:4-领域。
// Connected Component Analysis/Labeling By Seed-Filling Algorithm
// Author: www.icvpr.com
// Blog : http://blog.csdn.net/icvpr
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <stack>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
void icvprCcaBySeedFill(const cv::Mat&_binImg, cv::Mat&_lableImg)
{
// connected component analysis (4-component)
// use seed filling algorithm
// 1. begin with a foreground pixel and push its foreground neighbors into a stack
// 2. pop the top pixel on the stack and label it with the same label until the stack is empty
//
// foreground pixel: _binImg(x,y) = 1
// background pixel: _binImg(x,y) = 0
if (_binImg.empty() ||
_binImg.type() != CV_8UC1)
{
return
}
_lableImg.release()
_binImg.convertTo(_lableImg, CV_32SC1)
int label = 1 // start by 2
int rows = _binImg.rows - 1
int cols = _binImg.cols - 1
for (int i = 1i <rows-1i++)
{
int* data= _lableImg.ptr<int>(i)
for (int j = 1j <cols-1j++)
{
if (data[j] == 1)
{
std::stack<std::pair<int,int>>neighborPixels
neighborPixels.push(std::pair<int,int>(i,j)) // pixel position: <i,j>
++label // begin with a new label
while (!neighborPixels.empty())
{
// get the top pixel on the stack and label it with the same label
std::pair<int,int>curPixel = neighborPixels.top()
int curX = curPixel.first
int curY = curPixel.second
_lableImg.at<int>(curX, curY) = label
// pop the top pixel
neighborPixels.pop()
// push the 4-neighbors (foreground pixels)
if (_lableImg.at<int>(curX, curY-1) == 1)
{// left pixel
neighborPixels.push(std::pair<int,int>(curX, curY-1))
}
if (_lableImg.at<int>(curX, curY+1) == 1)
{// right pixel
neighborPixels.push(std::pair<int,int>(curX, curY+1))
}
if (_lableImg.at<int>(curX-1, curY) == 1)
{// up pixel
neighborPixels.push(std::pair<int,int>(curX-1, curY))
}
if (_lableImg.at<int>(curX+1, curY) == 1)
{// down pixel
neighborPixels.push(std::pair<int,int>(curX+1, curY))
}
}
}
}
}
}
3)颜色标记(用于显示)
// Connected Component Analysis/Labeling -- Color Labeling
// Author: www.icvpr.com
// Blog : http://blog.csdn.net/icvpr
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <stack>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
cv::Scalar icvprGetRandomColor()
{
uchar r = 255 * (rand()/(1.0 + RAND_MAX))
uchar g = 255 * (rand()/(1.0 + RAND_MAX))
uchar b = 255 * (rand()/(1.0 + RAND_MAX))
return cv::Scalar(b,g,r)
}
void icvprLabelColor(const cv::Mat&_labelImg, cv::Mat&_colorLabelImg)
{
if (_labelImg.empty() ||
_labelImg.type() != CV_32SC1)
{
return
}
std::map<int, cv::Scalar>colors
int rows = _labelImg.rows
int cols = _labelImg.cols
_colorLabelImg.release()
_colorLabelImg.create(rows, cols, CV_8UC3)
_colorLabelImg = cv::Scalar::all(0)
for (int i = 0i <rowsi++)
{
const int* data_src = (int*)_labelImg.ptr<int>(i)
uchar* data_dst = _colorLabelImg.ptr<uchar>(i)
for (int j = 0j <colsj++)
{
int pixelValue = data_src[j]
if (pixelValue >1)
{
if (colors.count(pixelValue) <= 0)
{
colors[pixelValue] = icvprGetRandomColor()
}
cv::Scalar color = colors[pixelValue]
*data_dst++ = color[0]
*data_dst++ = color[1]
*data_dst++ = color[2]
}
else
{
data_dst++
data_dst++
data_dst++
}
}
}
}
4)测试程序
// Connected Component Analysis/Labeling -- Test code
// Author: www.icvpr.com
// Blog : http://blog.csdn.net/icvpr
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <stack>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
int main(int argc, char** argv)
{
cv::Mat binImage = cv::imread("../icvpr.com.jpg", 0)
cv::threshold(binImage, binImage, 50, 1, CV_THRESH_BINARY_INV)
// connected component labeling
cv::Mat labelImg
icvprCcaByTwoPass(binImage, labelImg)
//icvprCcaBySeedFill(binImage, labelImg)
// show result
cv::Mat grayImg
labelImg *= 10
labelImg.convertTo(grayImg, CV_8UC1)
cv::imshow("labelImg", grayImg)
cv::Mat colorLabelImg
icvprLabelColor(labelImg, colorLabelImg)
cv::imshow("colorImg", colorLabelImg)
cv::waitKey(0)
return 0
}
1、找到Opencv的安装目录,例如安装目录在F盘,找到相应岩者缓的安装目录嫌咐如下所示
2、可以看到上图中有两个粗模目录文件夹,而要找的源代码就在source这个文件夹下,打开这个目录
3、在上图中找到modules,打开后可以看到很多文件夹,每个文件夹下都存放了不同类型领域的源代码。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)