koher / swift-image

SwiftImage: an image library in Swift with Swifty APIs and value semantics

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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
screen shot 2018-08-22 at 11 26 14 am

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;
      }
    }
  }

https://github.com/BradLarson/GPUImage2/blob/master/framework/Source/Operations/Shaders/ColorLocalBinaryPattern_GL.fsh

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.