enhancement/helper - LBP - local binary patterns
johndpope opened this issue · comments
https://youtu.be/-Ja-vLbHWLc?t=49
https://en.wikipedia.org/wiki/Local_binary_patterns
was thinking
extension Pixel{
func determinePattern()->LBP{
get the surrounding pixels
do the calculations
return 01010111
}
digging deeper into this - > there's a suite of these
BG-LBP (BackGround Local Binary Pattern) by Davarpanah et al. (2015)
CS-LBP (First-order Center-Symmetric Local Binary Patterns) by Heikkilä et al. (2006)
CS-LDP (Second-order Center-Symmetric Local Derivative Pattern) by Xue et al. (2011)
CS-SILTP (Center-Symmetric Scale Invariant Local Ternary Patterns) by Wu et al. (2013)
E-LBP (Extended LBP or Circular LBP) by Mdakane and Bergh (2012)
OC-LBP (Opponent Color Local Binary Pattern) by Maenpaa and Pietikainen (2004)
O-LBP (Original LBP) by Ojala et al. (2001)
SCS-LBP (Spatial extended Center-Symmetric Local Binary Pattern) by Xue et al. (2010)
SI-LTP (Scale Invariant Local Ternary Pattern) by Liao et al. (2010)
VAR-LBP (Variance-based LBP) by Ojala et al. (2002)
XCS-LBP (eXtended Center-Symmetric Local Binary Pattern) by Silva et al. (2015)
https://github.com/carolinepacheco/lbplibrary
void OLBP::OLBP_(const cv::Mat& src, cv::Mat& dst)
{
dst = cv::Mat::zeros(src.rows - 2, src.cols - 2, CV_8UC1);
for (int i = 1; i < src.rows - 1; i++) {
for (int j = 1; j < src.cols - 1; j++) {
_Tp center = src.at<_Tp>(i, j);
unsigned char code = 0;
code |= (src.at<_Tp>(i - 1, j - 1) > center) << 7;
code |= (src.at<_Tp>(i - 1, j) > center) << 6;
code |= (src.at<_Tp>(i - 1, j + 1) > center) << 5;
code |= (src.at<_Tp>(i, j + 1) > center) << 4;
code |= (src.at<_Tp>(i + 1, j + 1) > center) << 3;
code |= (src.at<_Tp>(i + 1, j) > center) << 2;
code |= (src.at<_Tp>(i + 1, j - 1) > center) << 1;
code |= (src.at<_Tp>(i, j - 1) > center) << 0;
dst.at<unsigned char>(i - 1, j - 1) = code;
}
}
}
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, textureCoordinate).r;
float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
float byteTally = 1.0 / 255.0 * step(centerIntensity, topRightIntensity);
byteTally += 2.0 / 255.0 * step(centerIntensity, topIntensity);
byteTally += 4.0 / 255.0 * step(centerIntensity, topLeftIntensity);
byteTally += 8.0 / 255.0 * step(centerIntensity, leftIntensity);
byteTally += 16.0 / 255.0 * step(centerIntensity, bottomLeftIntensity);
byteTally += 32.0 / 255.0 * step(centerIntensity, bottomIntensity);
byteTally += 64.0 / 255.0 * step(centerIntensity, bottomRightIntensity);
byteTally += 128.0 / 255.0 * step(centerIntensity, rightIntensity);
// TODO: Replace the above with a dot product and two vec4s
// TODO: Apply step to a matrix, rather than individually
gl_FragColor = vec4(byteTally, byteTally, byteTally, 1.0);
}
DRAFT
import EasyImagy
import Foundation
//typealias <#type name#> = <#type expression#>
func step(_ lhs:UInt8,_ rhs:UInt8)->UInt8{
if lhs > rhs{
return 1
}else{
return 0
}
}
extension UInt8 {
var toBinaryString: String {
return String(self, radix: 2)
}
var toHexaString: String {
return String(self, radix: 16)
}
}
extension Image where Pixel == UInt8 {
//or Pixel == RGBA<UInt32>
public func OLPB()->[Float]{
var histogram :[Float] = []
for x in self.xRange{
for y in self.yRange{
let olbp = OLBPat(x: x, y: y)
// histogram.append(olbp)
}
}
return histogram
}
//Original LBP
public func OLBPat(x: Int, y: Int)->UInt8{
let centerIntensity = self[x,y]
let bottomLeftIntensity = self[x-1,y-1]
let leftIntensity = self[x-1, y]
let topLeftIntensity = self[x-1, y+1]
let topIntensity = self[x+0, y+1]
let topRightIntensity = self[x+1,y+1]
let rightIntensity = self[x+1, y]
let bottomRightIntensity = self[x+1, y-1]
let bottomIntensity = self[x+0, y-1]
var code:UInt8 = 0
code |= step(centerIntensity, bottomLeftIntensity) << 7
code |= step(centerIntensity, leftIntensity ) << 6
code |= step(centerIntensity,topLeftIntensity ) << 5
code |= step(centerIntensity,topIntensity ) << 4
code |= step(centerIntensity,topRightIntensity) << 3
code |= step(centerIntensity, rightIntensity) << 2
code |= step(centerIntensity, bottomRightIntensity) << 1
code |= step(centerIntensity, bottomIntensity) << 0
print("code:",code.toBinaryString)
return code
}
}
code: 11
code: 10110000
code: 111
code: 1100000
code: 10000011
code: 0
code: 1100011
code: 11111
code: 100000
code: 111
code: 11000001
code: 1111110
code: 0
code: 110
code: 0
code: 0
code: 10000011
code: 100000
code: 11
code: 1111110
code: 10000011
code: 1100000
code: 10001111
code: 11
code: 1100000
code: 1
need to verify this is accurate.
will proceed as an extension. if there's interest / can resurrect this ticket.
reference osx code / project - https://github.com/johndpope/lbplibrary/blob/master/README.md