-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
508d6ea
commit 40cdbc1
Showing
9 changed files
with
289 additions
and
5 deletions.
There are no files selected for viewing
129 changes: 129 additions & 0 deletions
129
core/src/main/java/edu/wpi/grip/core/operations/composite/CropOperation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package edu.wpi.grip.core.operations.composite; | ||
|
||
import edu.wpi.grip.annotation.operation.Description; | ||
import edu.wpi.grip.annotation.operation.OperationCategory; | ||
import edu.wpi.grip.core.MatWrapper; | ||
import edu.wpi.grip.core.Operation; | ||
import edu.wpi.grip.core.sockets.InputSocket; | ||
import edu.wpi.grip.core.sockets.OutputSocket; | ||
import edu.wpi.grip.core.sockets.SocketHints; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.google.inject.Inject; | ||
|
||
import java.util.List; | ||
|
||
import static org.bytedeco.javacpp.opencv_core.Rect; | ||
|
||
|
||
/** | ||
* Crop an image to an exact width and height using one of several origin modes. Cropping | ||
* images down can be a useful optimization. | ||
*/ | ||
@Description(name = "Crop", | ||
summary = "Crop an image to an exact size", | ||
category = OperationCategory.IMAGE_PROCESSING, | ||
iconName = "crop") | ||
public class CropOperation implements Operation { | ||
|
||
private final InputSocket<MatWrapper> inputSocket; | ||
private final InputSocket<Number> xSocket; | ||
private final InputSocket<Number> ySocket; | ||
|
||
private final InputSocket<Number> widthSocket; | ||
private final InputSocket<Number> heightSocket; | ||
private final InputSocket<Origin> originSocket; | ||
|
||
private final OutputSocket<MatWrapper> outputSocket; | ||
|
||
@Inject | ||
@SuppressWarnings("JavadocMethod") | ||
public CropOperation(InputSocket.Factory inputSocketFactory, OutputSocket.Factory | ||
outputSocketFactory) { | ||
this.inputSocket = inputSocketFactory.create(SocketHints | ||
.createImageSocketHint("Input")); | ||
this.xSocket = inputSocketFactory.create(SocketHints.Inputs | ||
.createNumberSpinnerSocketHint("X", 100)); | ||
this.ySocket = inputSocketFactory.create(SocketHints.Inputs | ||
.createNumberSpinnerSocketHint("Y", 100)); | ||
this.widthSocket = inputSocketFactory.create(SocketHints.Inputs | ||
.createNumberSpinnerSocketHint("Width", 50)); | ||
this.heightSocket = inputSocketFactory.create(SocketHints.Inputs | ||
.createNumberSpinnerSocketHint("Height", 50)); | ||
this.originSocket = inputSocketFactory | ||
.create(SocketHints.createEnumSocketHint("Origin", Origin.CENTER)); | ||
|
||
this.outputSocket = outputSocketFactory.create(SocketHints | ||
.createImageSocketHint("Output")); | ||
} | ||
|
||
@Override | ||
public List<InputSocket> getInputSockets() { | ||
return ImmutableList.of( | ||
inputSocket, | ||
xSocket, | ||
ySocket, | ||
widthSocket, | ||
heightSocket, | ||
originSocket | ||
); | ||
} | ||
|
||
@Override | ||
public List<OutputSocket> getOutputSockets() { | ||
return ImmutableList.of( | ||
outputSocket | ||
); | ||
} | ||
|
||
@Override | ||
public void perform() { | ||
final MatWrapper input = inputSocket.getValue().get(); | ||
final MatWrapper output = outputSocket.getValue().get(); | ||
final Number x = xSocket.getValue().get(); | ||
final Number y = ySocket.getValue().get(); | ||
final Number width = widthSocket.getValue().get(); | ||
final Number height = heightSocket.getValue().get(); | ||
|
||
final Origin origin = originSocket.getValue().get(); | ||
|
||
final Rect regionOfInterest = new Rect( | ||
x.intValue() + (int) (origin.xOffsetMultiplier * width.intValue()), | ||
y.intValue() + (int) (origin.yOffsetMultiplier * height.intValue()), | ||
width.intValue(), | ||
height.intValue() | ||
); | ||
|
||
//apply() returns a sub-matrix; It does not modify the input Mat: https://github.com/WPIRoboticsProjects/GRIP/pull/926 | ||
if (input.isCpu()) { | ||
output.set(input.getCpu().apply(regionOfInterest)); | ||
} else { | ||
output.set(input.getGpu().apply(regionOfInterest)); | ||
} | ||
|
||
outputSocket.setValue(output); | ||
} | ||
|
||
private enum Origin { | ||
TOP_LEFT("Top Left", 0, 0), | ||
TOP_RIGHT("Top Right", -1, 0), | ||
BOTTOM_LEFT("Bottom Left", 0, -1), | ||
BOTTOM_RIGHT("Bottom Right", -1, -1), | ||
CENTER("Center", -.5, -.5); | ||
|
||
final String label; | ||
final double xOffsetMultiplier; | ||
final double yOffsetMultiplier; | ||
|
||
Origin(String label, double xOffsetMultiplier, double yOffsetMultiplier) { | ||
this.label = label; | ||
this.xOffsetMultiplier = xOffsetMultiplier; | ||
this.yOffsetMultiplier = yOffsetMultiplier; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return label; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
ui/src/main/resources/edu/wpi/grip/ui/codegeneration/cpp/operations/Crop.vm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* Crops an image. | ||
* | ||
* @param input The image on which to perform the crop. | ||
* @param x The x (horiontal) location of the crop. | ||
* @param y The y (vertical) location of the crop. | ||
* @param width The width(horizontal length) of the crop. | ||
* @param height The height(vertical length) of the crop. | ||
* @param origin The Origin of the crop. | ||
* @param output The image in which to store the output. | ||
*/ | ||
void $className::#func($step, ["input", "x", "y", "width", "height", "origin", "output"]) { | ||
double xOffsetMultiplier = 0; | ||
double yOffsetMultiplier = 0; | ||
switch(origin) { | ||
case TOP_RIGHT: | ||
xOffsetMultiplier = -1; | ||
break; | ||
case BOTTOM_LEFT: | ||
yOffsetMultiplier = -1; | ||
break; | ||
case BOTTOM_RIGHT: | ||
xOffsetMultiplier = -1; | ||
yOffsetMultiplier = -1; | ||
break; | ||
case CENTER: | ||
xOffsetMultiplier = -.5; | ||
yOffsetMultiplier = -.5; | ||
break; | ||
default: //origin == TOP_LEFT | ||
break; | ||
} | ||
cv::Rect regionOfInterest = cv::Rect( | ||
(int) (x + xOffsetMultiplier * width), | ||
(int) (y + yOffsetMultiplier * height), | ||
(int) width, | ||
(int) height | ||
); | ||
output = input(regionOfInterest); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
ui/src/main/resources/edu/wpi/grip/ui/codegeneration/java/operations/Crop.vm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* An indication of which type of which point on the box is used as the origin. | ||
* Choices are TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER | ||
*/ | ||
enum Origin { | ||
TOP_LEFT("Top Left", 0, 0), | ||
TOP_RIGHT("Top Right", -1, 0), | ||
BOTTOM_LEFT("Bottom Left", 0, -1), | ||
BOTTOM_RIGHT("Bottom Right", -1, -1), | ||
CENTER("Center", -.5, -.5); | ||
|
||
private final String label; | ||
private final double xOffsetMultiplier; | ||
private final double yOffsetMultiplier; | ||
|
||
Origin(String label, double xOffsetMultiplier, double yOffsetMultiplier) { | ||
this.label = label; | ||
this.xOffsetMultiplier = xOffsetMultiplier; | ||
this.yOffsetMultiplier = yOffsetMultiplier; | ||
} | ||
|
||
public static Origin get(String label){ | ||
switch(label){ | ||
case "Top Left": | ||
return TOP_LEFT; | ||
case "Top Right": | ||
return TOP_RIGHT; | ||
case "Bottom Left": | ||
return BOTTOM_LEFT; | ||
case "Bottom Right": | ||
return BOTTOM_RIGHT; | ||
default: | ||
return CENTER; | ||
} | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return label; | ||
} | ||
} | ||
|
||
/** | ||
* Crops an image. | ||
* @param input The image on which to perform the crop. | ||
* @param x The x (horiontal) location of the crop. | ||
* @param y The y (vertical) location of the crop. | ||
* @param width The width(horizontal length) of the crop. | ||
* @param height The height(vertical length) of the crop. | ||
* @param origin The Origin of the crop. | ||
* @param output The image in which to store the output. | ||
*/ | ||
private void $tMeth.name($step.name())(Mat input, double x, double y, double width, double height, Origin origin, Mat output) { | ||
|
||
Rect regionOfInterest = new Rect( | ||
(int) (x + origin.xOffsetMultiplier * width), | ||
(int) (y + origin.yOffsetMultiplier * height), | ||
(int) width, | ||
(int) height | ||
); | ||
input.submat(regionOfInterest).copyTo(output); | ||
} |
1 change: 1 addition & 0 deletions
1
ui/src/main/resources/edu/wpi/grip/ui/codegeneration/python/enums/Origin.vm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Origin = Enum('Origin', 'Top_Left Top_Right Bottom_Left Bottom_Right Center') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
ui/src/main/resources/edu/wpi/grip/ui/codegeneration/python/operations/Crop.vm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#needs("Origin") | ||
@staticmethod | ||
def $tMeth.name($step.name())(src, x, y, width, height, origin): | ||
"""Crops an image. | ||
Args: | ||
src: The source mat (numpy.ndarray). | ||
x: The x (horiontal) location of the crop. | ||
y: The y (vertical) location of the crop. | ||
width: The width(horizontal length) of the crop. | ||
height: The height(vertical length) of the crop. | ||
origin: The Origin of the crop. | ||
Returns: | ||
A numpy.ndarray that has been cropped. | ||
""" | ||
|
||
# origin is Top_Left | ||
x_offset_multiplier = 0 | ||
y_offset_multiplier = 0 | ||
|
||
if origin is Origin.Top_Right: | ||
x_offset_multiplier = -1 | ||
elif origin is Origin.Bottom_Left: | ||
y_offset_multiplier = -1 | ||
elif origin is Origin.Bottom_Right: | ||
x_offset_multiplier = -1 | ||
y_offset_multiplier = -1 | ||
elif origin is Origin.Center: | ||
x_offset_multiplier = -.5 | ||
y_offset_multiplier = -.5 | ||
|
||
# Flooring to keep consistency with Java | ||
x_start = int(x + x_offset_multiplier * width) | ||
x_end = int(x_start + width) | ||
|
||
y_start = int(y + y_offset_multiplier * height) | ||
y_end = int(y_start + height) | ||
|
||
return src[y_start: y_end, x_start : x_end] |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.