LBP算法原理
一、概述
LBP,全称Local Binary Pattern,局部二值模式,是一种能够描述图像纹理的算法,并且具有旋转不变性和灰度不变性等优点。
二、原始LBP算法解释
我们取3*3的像素块,然后利用中间的像素和旁边的8个像素点进行比较,大的就取1,小的就取0。得到全是0、1的结果后,我们采用顺时针的方式把这8个数连起来就形成了: 01111100 = 124 ,然后我们把它转换为十进制就是我们要得到的结果了。
三、圆形LBP
圆形的话:多了两个参数,一个是圆的半径r,还有一个就是点的个数(采样点)
四、圆形LBP算法之Java代码
public class ImageLBP extends Canvas {
JFrame jframe = new JFrame("图像lbp处理圆的");
BufferedImage bufferedImage,bufferedImage_gray,bufferedImage_lbp;
Image image,image_gray,image_lbp;
int rgb[][][],width,height; // x,y所对应的灰度值;
// 构造方法,面板显示
public ImageLBP(){
try {
bufferedImage = ImageIO.read(new File("D:\\EDge下载地址\\lena.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
width = bufferedImage.getWidth();
height =bufferedImage.getHeight();
rgb = new int[width+1][height+1][1];
jframe.setLayout(null);
// 定义位置
jframe.setBounds(200,200,800,600);
this.setBounds(0,0,800,600);
jframe.add(this);
jframe.setVisible(true);
bufferedImage_gray =gray(bufferedImage);
bufferedImage_lbp =lbp(bufferedImage_gray,2,8);
// 存起来
try{
ImageIO.write(bufferedImage_lbp,"jpg",new File("纹理边缘.jpg"));
System.out.println("修改后的图片已保存");
} catch(IOException e){
System.out.println("保存图片有错误");
e.printStackTrace();
}
}
@Override
public void paint(Graphics g) {
image =(Image)bufferedImage;
bufferedImage_gray =gray(bufferedImage);
image_lbp =(Image)lbp(bufferedImage_gray,2,8);
g.drawImage(image,0,0,null); // 显示原图
g.drawLine(350,10,350,600); // 中间的线
g.drawImage(image_lbp,370,0,null); // 显示处理后的图片
}
// 灰度处理
public BufferedImage gray(BufferedImage b){
// 定义:BufferedImage
bufferedImage_gray = new BufferedImage(width,height, BufferedImage.TYPE_3BYTE_BGR );
// 双层循环更改图片的RGB值,把得到的灰度值存到bufferedImage_end中,然后返回bufferedImage_end
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// 获取到(x,y)此像素点的Colo,转化为灰度
Color color = new Color(bufferedImage.getRGB(x,y));
int gray = (int)(color.getRed() * 0.299 + color.getGreen() * 0.587 + color.getBlue() *0.114);
Color color_end = new Color(gray,gray,gray);
bufferedImage_gray.setRGB(x,y,color_end.getRGB());
rgb[x][y][0] = gray;
}
}
return bufferedImage_gray;
}
/**
* radius:半径 p:采样点
*/
public BufferedImage lbp(BufferedImage bufferedImage,int radius,int neighbors){
bufferedImage_lbp = new BufferedImage(width,height, BufferedImage.TYPE_3BYTE_BGR );
// 根据公式:x =xc + R*cos(2πp/P) y = yc - R*sin(2πp/P);
//用于求采样点的数据;(从0开始到p结束)
/*
①:计算采样点的偏移值;
②:对偏移量进行上下取整;
③:将坐标偏移量映射到0-1之间
④:根据0-1之间的x,y的权重计算公式计算权重,权重与坐标具体位置无关,与坐标间的差值有关
⑤:根据双线性插值公式计算第k个采样点的灰度值
*/
// 这里先测试R = 2,和P = 8 的
// for循环里面需要从r开始,到 height-R-1 结束
for (int y = radius; y < height-radius-1; y++) {
for (int x = radius; x < width-radius-1; x++) {
int k[] = new int[neighbors];
int s = 0;
for(int n = 0;n < neighbors;n++){
int xy = rgb[x][y][0];
double rx = radius*Math.cos(2*Math.PI*n/neighbors);
double ry = -(radius*Math.sin(2*Math.PI*n/neighbors));
// 向上,向下取整
int x1 = (int)Math.ceil(rx);
int y1 = (int)Math.ceil(ry);
int x2 = (int)Math.floor(rx);
int y2 = (int)Math.ceil(ry);
// 映射
double tx = rx -x2;
double ty = ry -y2;
double w1 = (1-tx) * (1-ty);
double w2 = tx * (1-ty);
double w3 = (1-tx) * ty;
double w4 = tx * ty;
// 计算灰度值
double neighbour = rgb[x+x1][y+y1][0]*w1+rgb[x+x1][y+y2][0]*w2+rgb[x+x2][y+y1][0]*w3+rgb[x+x2][y+y2][0]*w4;
if(xy > neighbour){
k[n] = 0;
}else{
k[n] = 1;
int b = k[n]<<n;
s = s + b;
//System.out.println("此时的"+ s);
}
}
// 防止取16位的时候出问题
s = s%256;
//s = k[0]*128 + k[1]*64 + k[2]*32 + k[3]*16 + k[4]*8 + k[5]*4 + k[6]*2 +k[7]*1;
Color color = new Color(s,s,s);
bufferedImage_lbp.setRGB(x,y,color.getRGB());
}
}
return bufferedImage_lbp;
}
public static void main(String[] args) {
new ImageLBP();
}
}
五、结果展示
1、 半径= 1 点:8
2、 半径= 2 点:16
3、 半径= 2 点:8