#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
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 = 1; i < rows; i++)
{
int* data_preRow = _lableImg.ptr<int>(i-1) ; //用Mat::ptr()来获得指向某行元素的指针,在通过行数与通道数计算相应点的指针。
int* data_curRow = _lableImg.ptr<int>(i) ;
for (int j = 1; j < cols; j++)
{
if (data_curRow[j] == 1)
{
std::vector<int> neighborLabels ;
neighborLabels.reserve(2) ; // vector 的reserve增加了vector的capacity,但是它的size没有改变,加入新的元素时,要调用push_back()/insert()函数。
int leftPixel = data_curRow[j-1] ;
int upPixel = data_preRow[j] ;
if ( leftPixel > 1)
{
neighborLabels.push_back(leftPixel) ; //可以把vector简单理解为动态一维数组push_back作用是在这个一维数组尾部插入一个元素
}
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 = 1; k < 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 = 2; i < 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 = 0; i < rows; i++)
{
int* data = _lableImg.ptr<int>(i) ;
for (int j = 0; j < cols; j++)
{
int& pixelLabel = data[j] ;
pixelLabel = labelSet[pixelLabel] ;
}
}
}
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 = 0; i < rows; i++)
{
const int* data_src = (int*)_labelImg.ptr<int>(i) ;
uchar* data_dst = _colorLabelImg.ptr<uchar>(i) ;
for (int j = 0; j < cols; j++)
{
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++ ;
}
}
}
/* int counter[1000]={0};
for (int j = 0; j < cols; j++)
{
int oldpixel = 0;
for (int i = 100; i < rows; i++)
{
const int* data_src = (int*)_labelImg.ptr<int>(i) ;
int pixelValue = data_src[j] ;
if(pixelValue != oldpixel && pixelValue != 0)
{
counter[j]=counter[j]+1;
}
oldpixel = pixelValue;
}
// printf("%d ",counter[j]);
}
int max=0;
for(int i=0;i<=1000;i++)
{
if(counter[i]>max)
max=counter[i];
}
printf("连通区域数目: %d\n",max);
int max;
if(n==2)
{
ret = counter[0]>counter[1]?counter[0]:counter[1];
}
else
{
ret = counter[0]>max(counter+1,n-1)?counter[0]:max(counter+1,n-1);
}
return ret;
}
printf("max is %d\n", max(counter,1000));//zuidahua*/
}
void icvprGetLabelNumber(const cv::Mat& _labelImg)
{
int rows = _labelImg.rows ;
int cols = _labelImg.cols ;
int counter[10000]={0};
for (int j = 0; j < cols; j++)
{
int oldpixel = 0;
for (int i = 100; i < rows; i++)
{
const int* data_src = (int*)_labelImg.ptr<int>(i) ;
int pixelValue = data_src[j] ;
if(pixelValue != oldpixel && pixelValue != 0)
{
counter[j]=counter[j]+1;
}
oldpixel = pixelValue;
}
printf("%d ",counter[j]);
}
int max=0;
for(int j=0;j<=1000;j++)
{
if(counter[j]>max)
max=counter[j];
}
printf("\n连通区域数目: %d\n",max);
int value=0;
value=1000-(max-1)*10;
printf("量筒液面刻度为:%d\n",value);
}
int Otsu(IplImage* image)
{
//求出最佳阈值
int width;
width=image->width;
int height;
height=image->height;
int i,j,pixelSum,threshold;
pixelSum= width * height;
threshold = 0;
uchar* data ;
data=(uchar*)image->imageData;
float w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax;
//灰度级
float pixelPro[256];
int pixelCount[256];
deltaMax = 0;
//统计每个灰度级中像素的个数
for(i = 0; i < height; i++)
{
for(j = 0;j < width;j++)
{
pixelCount[(int)data[i * width + j]]++;
}