CTA算法
Conditional Texture Anisotropy
Roli 提 出 了 各 向 异 性 测 度 ( Conditional Texture Anisotropy, CTA) 的概念和计算原理, Nguyen 提出了各向异性测度的具体计算方法
选取某个像素的灰度,计算4个方向的P值,再计算CTA,然后把CTA从[0,1]映射到[0,255],生成灰度图,便于观察。
A是原图,B是灰度图
X是一个向量,由(均值,方差)组成。
m 和 σ 分别为整张图像的深度均值和标准差;
j表示4个方向,每个方向产生一条线,当成一个向量,线上有2d+1个像素,计算他们的P值
沿中心像素的 0°、45°、90° 和 135° 四个方向
L2为裂缝点,l1非裂缝点
裂缝的某个方向的P值会与其他方向的P值有很大的差距,使得CTA的值接近1,
非裂缝则是4个方向大致一样,使CTA接近0.
把4个P中的最大和最小值选出来计算CTA。
自己的代码测试效果图
上干货代码:(需要opencv 3.5以上版本)
CTA_function.cpp
#include "pch.h"
#include
#include "math.h"
#include
#include
#include
#include "opencv2/opencv.hpp"
#include
#include
#include
#include
#include "CTA_function.h"
using namespace std;
using namespace cv;
/*
计算每一个像素点的CTA
*/
/*
求均值,0度
X(rows)动,Y不动
*/
float fun_sum_1(pixel px1, int d, Mat pic) {
int i, j;
i = px1.x, j = px1.y;
float sum = 0;
int start, end;
start = i - d; end = i + d;
if (start < 0) {
start = 0;
}
if (end > pic.rows - 1) {
end = pic.rows - 1;
}
int temp;
int count = 0;
while (start <= end) {
int move = start;
temp = (int)pic.at(move, j);//pic[move][j];
sum = temp + sum;
start++;
count++;
}
return (float)sum / count;
}
/*
135度
X增Y增
*/
float fun_sum_2(pixel px1, int d, Mat pic) {
int i, j, x_start, y_start;
i = px1.x, j = px1.y;
float sum = 0;
int count = 0;
x_start = i - d, y_start = j - d;
for (int temp = 0; temp < 2 * d + 1; temp++) {
int _x = x_start + temp;
int _y = y_start + temp;
if (_x<0 || _y<0 || _x>pic.rows - 1 || _y>pic.cols - 1)continue;
sum = sum + (int)pic.at(_x, _y);//(int)pic.at(_x,_y);
count++;
}
return sum / count;
}
/*
求均值,90度,
*/
float fun_sum_3(pixel px1, int d, Mat pic) {
int i, j;
i = px1.x, j = px1.y;
float sum = 0;
int start, end;
start = j - d; end = j + d;
if (start < 0) {
start = 0;
}
//cout << "end=" << end;
if (end > pic.cols - 1) {
// cout << "end=" << end;
end = pic.cols - 1;
}
//cout << "pic=" << (int)pic.at(i,j) << endl;
int temp; int count = 0;
//cout << "start=" << start << endl;
while (start <= end) {
int move = start;
temp = (int)pic.at(i, move);//pic[i][move];
sum = temp + sum;
start++;
count++;
}
return (float)(sum / (count));
}
/*
45度
X增Y减
*/
float fun_sum_4(pixel px1, int d, Mat pic) {
int i, j, x_start, y_start;
float sum = 0;
int count = 0;
i = px1.x, j = px1.y;
x_start = i - d, y_start = j + d;
for (int temp = 0; temp < 2 * d + 1; temp++) {
int _x = x_start + temp;
int _y = y_start - temp;
if (_x<0 || _y<0 || _x>pic.rows - 1 || _y>pic.cols - 1) continue;
sum = sum + (int)pic.at(_x, _y);
count++;
}
return sum / count;
}
/*
差的平方的求和,0度
X动,Y不动
*/
float fun_dif_1(pixel px1, int d, float mean, Mat pic) {
int i, j, x_start, y_start;
i = px1.x, j = px1.y;
float sum = 0;
int count = 0;
x_start = i - d, y_start = j;
for (int temp = 0; temp < 2 * d + 1; temp++) {
int _x = x_start + temp;
int _y = y_start;
if (_x<0 || _y<0 || _x>pic.rows - 1 || _y>pic.cols - 1) continue;
sum = sum + ((int)pic.at(_x, _y) - mean)*((int)pic.at(_x, _y) - mean);
count++;
}
return sum;
}
/*
差的平方的求和,45度
X增Y增
*/
float fun_dif_2(pixel px1, int d, float mean, Mat pic) {
int i, j, x_start, y_start;
float sum = 0;
i = px1.x, j = px1.y;
x_start = i - d, y_start = j - d;
for (int temp = 0; temp < 2 * d + 1; temp++) {
int _x = x_start + temp;
int _y = y_start + temp;
if (_x<0 || _y<0 || _x>pic.rows - 1 || _y>pic.cols - 1)continue;
sum = sum + ((int)pic.at(_x, _y) - mean)*((int)pic.at(_x, _y) - mean);
}
return sum;
}
/*
差的平方的求和,90度
X不动,Y动
*/
float fun_dif_3(pixel px1, int d, float mean, Mat pic) {
///////////////////////////////
int i, j, x_start, y_start;
float sum = 0;
i = px1.x, j = px1.y;
x_start = i, y_start = j - d;
for (int temp = 0; temp < 2 * d + 1; temp++) {
int _x = x_start;
int _y = y_start + temp;
if (_x<0 || _y<0 || _x>pic.rows - 1 || _y>pic.cols - 1) continue;
sum = sum + ((int)pic.at(_x, _y) - mean)*((int)pic.at(_x, _y) - mean);
}
///////////////////////////////
return sum;
}
/*
差的平方的求和,135度
X增,Y减
*/
float fun_dif_4(pixel px1, int d, float mean, Mat pic) {
/////////////////////////////
int i, j, x_start, y_start;
float sum = 0;
i = px1.x, j = px1.y;
x_start = i - d, y_start = j + d;
for (int temp = 0; temp < 2 * d + 1; temp++) {
int _x = x_start + temp;
int _y = y_start - temp;
if (_x<0 || _y<0 || _x>pic.rows - 1 || _y>pic.cols - 1)continue;
sum = sum + ((int)pic.at(_x, _y) - mean)*((int)pic.at(_x, _y) - mean);
}
////////////////////////////
return sum;
}
/*
标准差
*/
float fun_dif(float means, Mat pic) {
float sum = 0;
for (int i = 0; i < pic.rows; i++) {
for (int j = 0; j < pic.cols; j++) {
float temp = (float)((int)pic.at(i, j)) - means;
sum = sum + (temp*temp);
}
return sqrt(sum);
}
}
//ok
float fun_means(Mat pic) {
int row = pic.rows;
int col = pic.cols;
float means = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++)
{
int grayvalue = (int)pic.at(i, j);
means = means + (float)grayvalue / (row*col);
}
}
return means;
}
float fun_p(float mean1, float stdev1, float means, float stdev)
{
float D, deta;
D = sqrt(means*means + stdev * stdev);
deta = sqrt((means - mean1)*(means - mean1) + (stdev - stdev1) * (stdev - stdev1));
return ((D - deta) / deta);
}
float fun_CTA(pixel px1, int d, Mat pic) {
int row = pic.rows;
int col = pic.cols;
float cta_num;
//生成均值//ok
float means, stdev;//全局的均值和方差
means = fun_means(pic);
//生成标准差
stdev = fun_dif(means, pic);
//生成4个方向向量
float mean1, stdev1;//0度的均值和方差
float mean2, stdev2;//45度
float mean3, stdev3;//90度
float mean4, stdev4;//135度
mean1 = fun_sum_1(px1, d, pic) / (2 * d + 1);
stdev1 = sqrt(fun_dif_1(px1, d, mean1, pic));//求方差
//计算每个向量的P()
//float p1, p2, p3, p4;
mean2 = fun_sum_2(px1, d, pic) / (2 * d + 1);
stdev2 = sqrt(fun_dif_2(px1, d, mean1, pic));
mean3 = fun_sum_3(px1, d, pic) / (2 * d + 1);
stdev3 = sqrt(fun_dif_3(px1, d, mean1, pic));
mean4 = fun_sum_4(px1, d, pic) / (2 * d + 1);
stdev4 = sqrt(fun_dif_4(px1, d, mean1, pic));
float p[4];
p[0] = fun_p(mean1, stdev1, means, stdev);
p[1] = fun_p(mean2, stdev2, means, stdev);
p[2] = fun_p(mean3, stdev3, means, stdev);
p[3] = fun_p(mean4, stdev4, means, stdev);
//找min和max
float min, max;
std::sort(p, p + 4);
min = p[0];
max = p[3];
cta_num = (max - min) / max;
return cta_num;
}
/*
映射[0,1]->[0,255]
*/
int Projection01to0255(float cta) {
int grey = 0;
grey = (int)(cta * 256);
return grey;
}
Mat CTA(Mat inPut, int distance) {
Mat source = inPut;//图片路径
Mat gray;
cvtColor(source, gray, COLOR_RGB2GRAY, 1);
Mat CTA_image(gray.rows, gray.cols, CV_8UC1);
cvtColor(source, CTA_image, COLOR_BGR2GRAY, 1);
pixel p1;
p1.x = 0;
p1.y = 0;
for (int i = 0; i < gray.rows ; ++i)
for (int j = 0; j < gray.cols ; ++j)
{ float cta_num;
p1.x = i; p1.y = j;
cta_num = fun_CTA(p1, 10, gray);
int gray = Projection01to0255(cta_num);
CTA_image.at(i, j) = cta_num;
}
return CTA_image;
}
void test()
{
cout << "cta test" << endl;
}
CTA_function.h
#include "pch.h"
#include
#include "math.h"
#include
#include
#include
#include "opencv2/opencv.hpp"
#include
#include
#include
#include
using namespace std;
using namespace cv;
typedef struct
{
int x;
int y;
}pixel;
float fun_sum_1(pixel px1, int d, Mat pic);
float fun_sum_2(pixel px1, int d, Mat pic);
float fun_sum_3(pixel px1, int d, Mat pic);
float fun_sum_4(pixel px1, int d, Mat pic);
float fun_dif_1(pixel px1, int d, float mean, Mat pic);
float fun_dif_2(pixel px1, int d, float mean, Mat pic);
float fun_dif_3(pixel px1, int d, float mean, Mat pic);
float fun_dif_4(pixel px1, int d, float mean, Mat pic);
float fun_dif(float means, Mat pic);
float fun_means(Mat pic);
float fun_p(float mean1, float stdev1, float means, float stdev);
float fun_CTA(pixel px1, int d, Mat pic);
int Projection01to0255(float cta);
Mat CTA(Mat inPut,int distance) ;
void test();
之后发现,计算速度很慢,又进行了多线程的优化,是原来的2.5倍速(笑)。
这里给出文件:
CTA_function_thread.cpp
最后,引用论文是
【Automatic Detection and Classification of Defect on road Pavement using Anisotropy Measure】 Tien Sy Nguyen, Manuel Avila, St´ephane Begot