|
@@ -12,7 +12,7 @@
|
|
|
using namespace cv;
|
|
|
using namespace std;
|
|
|
using namespace OTSDATA;
|
|
|
-/***** 求两点间距离*****/
|
|
|
+/***** get the distance between two point*****/
|
|
|
float getDistance(Point pointO, Point pointA)
|
|
|
{
|
|
|
float distance;
|
|
@@ -21,16 +21,16 @@ float getDistance(Point pointO, Point pointA)
|
|
|
return distance;
|
|
|
|
|
|
}
|
|
|
-/***** 点到直线的距离:P到AB的距离*****/
|
|
|
-//P为线外一点,AB为线段两个端点
|
|
|
+/***** get the distance betweem a point and a line*****/
|
|
|
+//p is the point, A and B are the two points of the line
|
|
|
float getDist_P2L(Point pointP, Point pointA, Point pointB)
|
|
|
{
|
|
|
- //求直线方程
|
|
|
+ //get the line equation Ax+By+C=0
|
|
|
int A = 0, B = 0, C = 0;
|
|
|
A = pointA.y - pointB.y;
|
|
|
B = pointB.x - pointA.x;
|
|
|
C = pointA.x * pointB.y - pointA.y * pointB.x;
|
|
|
- //代入点到直线距离公式
|
|
|
+ //put the point into the line distance equation
|
|
|
float distance = 0;
|
|
|
distance = ((float)abs(A * pointP.x + B * pointP.y + C)) / ((float)sqrtf(A * A + B * B));
|
|
|
return distance;
|
|
@@ -44,27 +44,27 @@ int Side(Point P1, Point P2, Point point)
|
|
|
void FindInnerCircleInContour(vector<Point> contour, Point& center, int& radius)
|
|
|
{
|
|
|
Rect r = boundingRect(contour);
|
|
|
- int nL = r.x, nR = r.br().x; //轮廓左右边界
|
|
|
- int nT = r.y, nB = r.br().y; //轮廓上下边界
|
|
|
+ int nL = r.x, nR = r.br().x; //the left and right boundaries of the contour
|
|
|
+ int nT = r.y, nB = r.br().y; //the top and bottom boundaries of the contour
|
|
|
|
|
|
double dist = 0;
|
|
|
double maxdist = 0;
|
|
|
|
|
|
- for (int i = nL; i < nR; i++) //列
|
|
|
+ for (int i = nL; i < nR; i++) //column
|
|
|
{
|
|
|
- for (int j = nT; j < nB; j++) //行
|
|
|
+ for (int j = nT; j < nB; j++) //row
|
|
|
{
|
|
|
- //计算轮廓内部各点到最近轮廓点的距离
|
|
|
+ //calculate the distance between the inside point and the contour
|
|
|
dist = pointPolygonTest(contour, Point(i, j), true);
|
|
|
if (dist > maxdist)
|
|
|
{
|
|
|
- //求最大距离,只有轮廓最中心的点才距离最大
|
|
|
+ //get the point with the maximum distance
|
|
|
maxdist = dist;
|
|
|
center = Point(i, j);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- radius = maxdist; //圆半径
|
|
|
+ radius = maxdist; //the radius is the maximum distance between the inside point and the contour
|
|
|
}
|
|
|
BOOL GetParticleAverageChord(std::vector<Point> listEdge, double a_PixelSize, double& dPartFTD)
|
|
|
{
|
|
@@ -192,14 +192,15 @@ CBSEImgPtr GetBSEImgFromMat(Mat inImg)
|
|
|
return bse;
|
|
|
}
|
|
|
/***********************************************************
|
|
|
-增强算法的原理在于先统计每个灰度值在整个图像中所占的比例
|
|
|
-然后以小于当前灰度值的所有灰度值在总像素中所占的比例,作为增益系数
|
|
|
-对每一个像素点进行调整。由于每一个值的增益系数都是小于它的所有值所占
|
|
|
-的比例和。所以就使得经过增强之后的图像亮的更亮,暗的更暗。
|
|
|
+
|
|
|
+the enhancement algorithm is based on the proportion of each gray value in the entire image
|
|
|
+Then, as a gain factor, the proportion of all gray values less than the current gray value in the total pixels
|
|
|
+Each pixel point is adjusted. Since the gain factor of each value is the sum of the proportions of all values less than it.
|
|
|
+So the image after enhancement is brighter and darker.
|
|
|
************************************************************/
|
|
|
void ImageStretchByHistogram(const Mat& src, Mat& dst)
|
|
|
{
|
|
|
- //判断传入参数是否正常
|
|
|
+ //judge the size of the two images
|
|
|
if (!(src.size().width == dst.size().width))
|
|
|
{
|
|
|
cout << "error" << endl;
|
|
@@ -214,7 +215,7 @@ void ImageStretchByHistogram(const Mat& src, Mat& dst)
|
|
|
int width = src.size().width;
|
|
|
long wMulh = height * width;
|
|
|
|
|
|
- //统计每一个灰度值在整个图像中所占个数
|
|
|
+ //statistics of each gray value in the image
|
|
|
for (int x = 0; x < width; x++)
|
|
|
{
|
|
|
for (int y = 0; y < height; y++)
|
|
@@ -224,13 +225,13 @@ void ImageStretchByHistogram(const Mat& src, Mat& dst)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //使用上一步的统计结果计算每一个灰度值所占总像素的比例
|
|
|
+ //using the number of each gray value to calculate the proportion of each gray value in the total pixels
|
|
|
for (int i = 0; i < 256; i++)
|
|
|
{
|
|
|
p[i] = num[i] / wMulh;
|
|
|
}
|
|
|
|
|
|
- //计算每一个灰度值,小于当前灰度值的所有灰度值在总像素中所占的比例
|
|
|
+ //calculate the cumulative distribution function
|
|
|
//p1[i]=sum(p[j]); j<=i;
|
|
|
for (int i = 0; i < 256; i++)
|
|
|
{
|
|
@@ -238,7 +239,7 @@ void ImageStretchByHistogram(const Mat& src, Mat& dst)
|
|
|
p1[i] += p[k];
|
|
|
}
|
|
|
|
|
|
- //以小于当前灰度值的所有灰度值在总像素中所占的比例,作为增益系数对每一个像素点进行调整。
|
|
|
+ //using the cumulative distribution function to adjust the pixel value
|
|
|
for (int y = 0; y < height; y++)
|
|
|
{
|
|
|
for (int x = 0; x < width; x++) {
|
|
@@ -248,13 +249,13 @@ void ImageStretchByHistogram(const Mat& src, Mat& dst)
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
-//调整图像对比度
|
|
|
+//adjust the contrast of the image
|
|
|
Mat AdjustContrastY(const Mat& img)
|
|
|
{
|
|
|
Mat out = Mat::zeros(img.size(), CV_8UC1);
|
|
|
Mat workImg = img.clone();
|
|
|
|
|
|
- //对图像进行对比度增强
|
|
|
+ //enhance the image
|
|
|
ImageStretchByHistogram(workImg, out);
|
|
|
|
|
|
return Mat(out);
|
|
@@ -267,7 +268,7 @@ void CVRemoveBG(const cv::Mat& img, cv::Mat& dst,int bgstart,int bgend/*, long&
|
|
|
int max_gray = bgend;
|
|
|
if (img.empty())
|
|
|
{
|
|
|
- std::cout << "图像为空";
|
|
|
+ std::cout << "empty image";
|
|
|
return;
|
|
|
}
|
|
|
Mat image = img.clone();
|
|
@@ -275,7 +276,7 @@ void CVRemoveBG(const cv::Mat& img, cv::Mat& dst,int bgstart,int bgend/*, long&
|
|
|
{
|
|
|
cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
|
|
|
}
|
|
|
- //lut 查找表 取规定范围的灰度图 排除拼图时四周灰度为255区域 以及 灰度值较低的区域
|
|
|
+ //lut: lookup table,exclude the gray value less than min_gray and greater than max_gray
|
|
|
uchar lutvalues[256];
|
|
|
for (int i = 0; i < 256; i++)
|
|
|
{
|
|
@@ -292,13 +293,13 @@ void CVRemoveBG(const cv::Mat& img, cv::Mat& dst,int bgstart,int bgend/*, long&
|
|
|
cv::Mat lutpara(1, 256, CV_8UC1, lutvalues);
|
|
|
cv::LUT(image, lutpara, image);
|
|
|
cv::Mat out_fill0, out_fill;
|
|
|
- //开运算 获得x>5 的元素
|
|
|
+ //open calculation
|
|
|
cv::morphologyEx(image, out_fill0, cv::MorphTypes::MORPH_OPEN, cv::getStructuringElement(0, cv::Size(5, 1)), cv::Point(-1, -1), 1);
|
|
|
cv::morphologyEx(image, out_fill, cv::MorphTypes::MORPH_OPEN, cv::getStructuringElement(0, cv::Size(1, 5)), cv::Point(-1, -1), 1);
|
|
|
out_fill = out_fill + out_fill0;
|
|
|
- //闭运算
|
|
|
+ //close calculation
|
|
|
cv::morphologyEx(out_fill, out_fill, cv::MorphTypes::MORPH_CLOSE, cv::getStructuringElement(0, cv::Size(3, 3)), cv::Point(-1, -1), 1);
|
|
|
- //二值
|
|
|
+ //binary thresholding
|
|
|
cv::threshold(out_fill, out_fill, 1, 255, cv::ThresholdTypes::THRESH_BINARY);
|
|
|
dst = out_fill.clone();
|
|
|
}
|
|
@@ -351,7 +352,7 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
auto a = mean[0];
|
|
|
auto d = std[0];
|
|
|
bool direct_binary = false;
|
|
|
- if (a > 240)//全亮背景 暗颗粒;直接二值提取 ;特殊情况
|
|
|
+ if (a > 240)//bright background, dark particle;direct binary process ;particular case
|
|
|
{
|
|
|
direct_binary = true;
|
|
|
}
|
|
@@ -363,11 +364,11 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
{
|
|
|
both_black_bright = true;
|
|
|
}
|
|
|
- //自适应滤波
|
|
|
+ //adaptive manifold filter
|
|
|
cv::Ptr<cv::ximgproc::AdaptiveManifoldFilter> pAdaptiveManifoldFilter
|
|
|
= cv::ximgproc::createAMFilter(3.0, 0.1, true);
|
|
|
cv::Mat temp1, dst_adapt;
|
|
|
- cv::Mat out_thresh;//提取前景二值图
|
|
|
+ cv::Mat out_thresh;//get the binary image of the extracted particle
|
|
|
if (direct_binary)
|
|
|
{
|
|
|
int min = 30;
|
|
@@ -387,7 +388,7 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
cv::Mat image_Negate;
|
|
|
if (both_black_bright)
|
|
|
{
|
|
|
- //提取暗物体
|
|
|
+ //get the dark object
|
|
|
cv::Mat black_t;
|
|
|
int min_gray = 0;
|
|
|
float segma_b = 1.5;
|
|
@@ -409,7 +410,7 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
cv::Mat lutpara(1, 256, CV_8UC1, lutvalues);
|
|
|
cv::LUT(dst_adapt, lutpara, black_t);
|
|
|
|
|
|
- //提取亮物体
|
|
|
+ //get the bright object
|
|
|
cv::Mat bright_t;
|
|
|
int min_gray_bright = int(a + d * segma_b);
|
|
|
int max_gray_bright = 255;
|
|
@@ -434,8 +435,8 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- //统一将提取物转换为暗物质亮背景
|
|
|
- if (!direct_binary && (parame0 == 0))//暗物体,暗背景
|
|
|
+ //convert the image to its negative image
|
|
|
+ if (!direct_binary && (parame0 == 0))//dark particle,bright background
|
|
|
{
|
|
|
image_Negate = image;
|
|
|
}
|
|
@@ -444,29 +445,29 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
dst_adapt = ~dst_adapt;
|
|
|
image_Negate = ~image;
|
|
|
}
|
|
|
- //三角阈值
|
|
|
+ //triangle thresholding
|
|
|
auto result_THRESH_TRIANGLE = cv::threshold(dst_adapt, out_thresh, 100, 255, cv::ThresholdTypes::THRESH_TRIANGLE | img_ThresholdTypes);
|
|
|
cv::Mat extractedImage;
|
|
|
cv::bitwise_and(image_Negate, image_Negate, extractedImage, out_thresh = out_thresh > 0); // 使用mask > 0将mask转换为二值图像
|
|
|
- // 计算提取区域的均值和方差
|
|
|
+ //calculate the mean and std of the extracted image
|
|
|
cv::Scalar mean1, std1;
|
|
|
cv::meanStdDev(extractedImage, mean1, std1, out_thresh);
|
|
|
auto mean0 = mean1[0];
|
|
|
auto std0 = std1[0];
|
|
|
- // binaryImage二值图像;去除部分扩大区域
|
|
|
+ // binaryImage;remove the pixels greater than the threshold
|
|
|
cv::Mat binaryImage = cv::Mat::zeros(image_Negate.size(), image_Negate.type());
|
|
|
- //筛选系数
|
|
|
+ //the filter coefficient
|
|
|
int segma = 4;
|
|
|
float filter_gray = (mean0 + std0 / segma);
|
|
|
//filter_gray = result_THRESH_TRIANGLE;
|
|
|
for (int y = 0; y < extractedImage.rows; ++y) {
|
|
|
for (int x = 0; x < extractedImage.cols; ++x) {
|
|
|
if (extractedImage.at<uchar>(y, x) >= 1 && extractedImage.at<uchar>(y, x) <= (int)(filter_gray)) {
|
|
|
- binaryImage.at<uchar>(y, x) = 255; // 设置为白色(255)
|
|
|
+ binaryImage.at<uchar>(y, x) = 255; //set to white(255)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- //直接提取小于parame2(默认为30)的区域
|
|
|
+ //get the less than parame2(default 30)area
|
|
|
cv::Mat thing_area;
|
|
|
cv::threshold(image_Negate, thing_area, parame2, 255, img_ThresholdTypes);
|
|
|
//out_thresh = binaryImage ;
|
|
@@ -475,9 +476,9 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
|
|
|
}
|
|
|
cv::Mat img_draw = cv::Mat::zeros(image.size(), CV_8UC3);
|
|
|
- //连通域过滤绘制颗粒
|
|
|
+ //get the connected components
|
|
|
|
|
|
- //随机颜色
|
|
|
+ //random color
|
|
|
cv::RNG rng(10086);
|
|
|
cv::Mat labels, stats, controids;
|
|
|
int number = cv::connectedComponentsWithStats(out_thresh, labels, stats, controids, 8, CV_16U);
|
|
@@ -494,7 +495,7 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
}
|
|
|
draw_indexs.push_back(i);
|
|
|
}
|
|
|
- //染色 过滤
|
|
|
+ //color the connected components
|
|
|
int w = img_draw.cols;
|
|
|
int h = img_draw.rows;
|
|
|
cv::Vec3b color = cv::Vec3b(0, 0, 255);
|
|
@@ -516,14 +517,14 @@ void AutoRemove_background_OTS(const cv::Mat& img, cv::Mat& dst, int black_thing
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //原图染色
|
|
|
+ //color the particle on the original image
|
|
|
//cv::Mat img_blend;
|
|
|
- //double alpha = 0.7; // 设定img1的权重
|
|
|
- //double beta = 1 - alpha; // 计算img2的权重
|
|
|
+ //double alpha = 0.7; // set the weight of img1
|
|
|
+ //double beta = 1 - alpha; // calculate the weight of img2
|
|
|
//cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
|
|
|
//cv::addWeighted(image, alpha, img_draw, beta, 0.0, img_blend);
|
|
|
//dst = img_blend.clone();
|
|
|
- //二值图
|
|
|
+ //binary image
|
|
|
vector<cv::Mat> outs;
|
|
|
cv::split(img_draw, outs);
|
|
|
dst = outs[2].clone();
|