Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,41 @@

<groupId>com.github.quadflask</groupId>
<artifactId>smartcrop-java</artifactId>
<version>1.0-SNAPSHOT</version>
<version>2.8</version>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>

<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>3.2</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
Expand All @@ -34,5 +54,4 @@
</plugin>
</plugins>
</build>

</project>
123 changes: 123 additions & 0 deletions src/main/java/com/github/quadflask/smartcrop/OpencvDetect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package com.github.quadflask.smartcrop;

import lombok.extern.slf4j.Slf4j;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.objdetect.CascadeClassifier;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
public class OpencvDetect {

private static OpencvDetect instance = new OpencvDetect();
private static CascadeClassifier cascadeClassifier;
private static String frontalfacePath;

static {
try {
String osName = System.getProperty("os.name");
if (osName.startsWith("Windows")) {
System.loadLibrary("lib" + Core.NATIVE_LIBRARY_NAME);
} else if (osName.startsWith("Mac")) {
System.load("/usr/local/lib/lib" + Core.NATIVE_LIBRARY_NAME + ".dylib");

} else if (osName.startsWith("Linux")) {
System.load("/usr/local/lib/lib" + Core.NATIVE_LIBRARY_NAME + ".so");
}
} catch (Throwable t) {
log.error("Load OpenCV lib error.", t);
}
}


public static OpencvDetect getInstance() {
return instance;
}


public Crop[] detectFace(String imagePath) {
Mat image = Imgcodecs.imread(imagePath);
MatOfRect faceDetections = new MatOfRect();
cascadeClassifier.detectMultiScale(image, faceDetections);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this classifier use a grey scale image?

Rect[] rects = faceDetections.toArray();
return toCrop(rects);
}

public Crop[] detectFace(byte[] imageBase64) {

try {
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(imageBase64));
return detectFace(bi);

} catch (Exception e) {
log.error("dateface error.", e);
}

return null;
}


public Crop[] detectFace(BufferedImage bi) {

try {
Mat image = img2Mat(bi);
MatOfRect faceDetections = new MatOfRect();
cascadeClassifier.detectMultiScale(image, faceDetections);
Rect[] rects = faceDetections.toArray();
return toCrop(rects);
} catch (Throwable t) {

}
return null;
}

/**
* the file is '~/opencvXX/haarcascades/haarcascade_frontalface_alt.xml"'
*
* @param frontalfacePath
*/
public void SetFrontalFacePath(String frontalfacePath) {
this.frontalfacePath = frontalfacePath;
cascadeClassifier = new CascadeClassifier(frontalfacePath);
}


private Crop[] toCrop(Rect[] rect) {

List<Crop> cropList = new ArrayList<>();
if (rect != null) {

Arrays.stream(rect).forEach(r -> cropList.add(new Crop(r.x, r.y, r.width, r.height)));

}

Crop[] crops = new Crop[cropList.size()];
cropList.toArray(crops);
return crops;
}


private Mat img2Mat(BufferedImage im) {
// Convert INT to BYTE
//im = new BufferedImage(im.getWidth(), im.getHeight(),BufferedImage.TYPE_3BYTE_BGR);
// Convert bufferedimage to byte array
byte[] pixels = ((DataBufferByte) im.getRaster().getDataBuffer()).getData();

// Create a Matrix the same size of image
Mat image = new Mat(im.getHeight(), im.getWidth(), CvType.CV_8UC3);
// Fill Matrix with image values
image.put(0, 0, pixels);

return image;

}


}
48 changes: 44 additions & 4 deletions src/main/java/com/github/quadflask/smartcrop/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
public class Options {
public static final Options DEFAULT = new Options();

private boolean debug = false;
private int cropWidth = 100;
private int cropHeight = 100;
private float detailWeight = .2f;
private float[] skinColor = {0.7f, 0.57f, 0.44f};
private float[] skinColor = {0.78f, 0.57f, 0.44f};
private float skinBias = .01f;
private float skinBrightnessMin = 0.2f;
private float skinBrightnessMax = 1.0f;
Expand All @@ -21,18 +22,29 @@ public class Options {
private float saturationBrightnessMax = 0.9f;
private float saturationThreshold = 0.4f;
private float saturationBias = 0.2f;
private float saturationWeight = 0.3f;
private float saturationWeight = 0.1f;
// step * minscale rounded down to the next power of two should be good
private int scoreDownSample = 8;
// private int step = 8;
public int step = 8;
private float scaleStep = 0.1f;
private float minScale = 0.8f;
private float maxScale = 1.0f;
private float edgeRadius = 0.4f;
private float edgeWeight = -20f;
private float outsideImportance = -.5f;
private boolean ruleOfThirds = false;
private float prescale = 1f;
private float boostWeight = 100.0f;
private boolean ruleOfThirds = true;
private int bufferedBitmapType = BufferedImage.TYPE_INT_ARGB;
private Crop[] boost = null;

public void setCropWidth(int cropWidth) {
this.cropWidth = cropWidth;
}

public void setCropHeight(int cropHeight) {
this.cropHeight = cropHeight;
}

public int getCropWidth() {
return cropWidth;
Expand Down Expand Up @@ -223,6 +235,26 @@ public Options outsideImportance(float outsideImportance) {
return this;
}

public Crop[] getBoost() {
return boost;
}

public void setBoost(Crop[] boost) {
this.boost = boost;
}

public float getBoostWeight() {
return boostWeight;
}

public float getPrescale() {
return prescale;
}

public void setPrescale(float prescale) {
this.prescale = prescale;
}

public boolean isRuleOfThirds() {
return ruleOfThirds;
}
Expand All @@ -240,4 +272,12 @@ public Options bufferedBitmapType(int bufferedBitmapType) {
this.bufferedBitmapType = bufferedBitmapType;
return this;
}

public boolean isDebug() {
return debug;
}

public void setDebug(boolean debug) {
this.debug = debug;
}
}
1 change: 1 addition & 0 deletions src/main/java/com/github/quadflask/smartcrop/Score.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public class Score {
public float detail;
public float saturation;
public float skin;
public float boost;
public float total;
}
Loading