There will be three buttons be placed on the top of the window, at the initial, button 1 and button 2 should be display. Once button 2 is being clicked, it should execute it function and be change to button3. Other other hand when button 3 is clicked, it should execute it function and be changed to button 2.
Here is the code that I have write so far.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.swing.*;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.objdetect.CascadeClassifier;
class FaceArea {
private String currentImage;
FaceArea() {
currentImage = "";
}
String getCurrentImage() {
return currentImage;
}
void setCurrentImage(String imageName) {
currentImage = imageName;
}
void FaceAreas(Graphics g, Rect[] faceAreas) {
if (currentImage.equals("imageV1.jpg")) {
V1(g, faceAreas);
} else if (currentImage.equals("imageV2.jpg")) {
V2(g, faceAreas);
}
}
private void V1(Graphics g, Rect[] faceAreas) {
g.setColor(Color.yellow);
for (Rect rect : faceAreas) {
g.drawRect((rect.x) / 2 - 20, rect.y / 2 + 400, rect.width / 3 + 20, rect.height / 3 + 20);
}
}
private void V2(Graphics g, Rect[] faceAreas) {
g.setColor(Color.yellow);
for (Rect rect : faceAreas) {
g.drawRect((rect.x - 10) / 2, rect.y / 2 + 400, rect.width / 3 + 25, rect.height / 3 + 25);
}
}
void Text(Graphics g, JTextArea textArea) {
if (currentImage.equals("message.txt")) {
g.setColor(Color.blue);
g.setFont(new Font("Arial", Font.PLAIN, 16));
String[] lines = textArea.getText().split("\n");
int y = 420;
for (String line : lines) {
g.drawString(line, 10, y);
y += g.getFontMetrics().getHeight();
}
}
}
}
public class PlayWithFace extends JFrame {
BufferedImage bimage1, bimage2;
Mat src1, src2;
String FromCamera = "FromCamera.jpg";
ArrayList<String> imageFiles;
Iterator<String> imageIterator;
String path = "/opt/homebrew/Cellar/opencv/4.8.1_1/share/opencv4/haarcascades/";
String cascade = "haarcascade_frontalface_alt.xml";
Rect[] faceArea1 = null;
Rect[] faceArea2 = null;
int count = 0;
JButton button1, button2, button3;
FaceArea faceArea;
JTextArea textArea;
private BufferedImage originalBimage1; // Added for storing the original image
public PlayWithFace() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
setTitle("Play with Face");
setSize(500, 760);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea = new JTextArea();
faceArea = new FaceArea();
detect();
repaint();
button1 = new JButton("Next Image");
button1.addActionListener(e -> loadNextImage());
button2 = new JButton("Change Face");
button2.addActionListener(e -> changeFace());
button3 = new JButton("Return Face");
button3.addActionListener(e -> returnFace());
JPanel buttonPanel = new JPanel();
buttonPanel.add(button1);
buttonPanel.add(button2);
setLayout(new BorderLayout());
add(buttonPanel, BorderLayout.NORTH);
setVisible(true);
}
private void Text(String filePath) {
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
content.append(line).append("\n");
}
textArea.setText(content.toString());
faceArea.setCurrentImage("message.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadNextImage() {
if (imageIterator.hasNext()) {
String nextImage = imageIterator.next();
if (nextImage.endsWith(".jpg") || nextImage.endsWith(".jpeg") || nextImage.endsWith(".png")) {
src2 = Imgcodecs.imread(nextImage);
bimage2 = matToBufferedImage(src2);
faceArea2 = getArea(cascade, src2);
faceArea.setCurrentImage(nextImage);
} else if (nextImage.endsWith(".txt")) {
Text(nextImage);
}
repaint();
}
}
private void changeFace() {
if (faceArea2 != null) {
Rect[] faceArea2Copy = Arrays.copyOf(faceArea2, faceArea2.length);
if (bimage1 != null && bimage2 != null) {
Graphics2D g2d = bimage1.createGraphics();
if (faceArea.getCurrentImage().equals("imageV1.jpg")) {
for (Rect rect : faceArea2Copy) {
BufferedImage facePart = bimage2.getSubimage(rect.x, rect.y, rect.width, rect.height);
g2d.drawImage(facePart, rect.x + 45, rect.y - 140,
rect.width + 360, rect.height + 390, this);
}
} else if (faceArea.getCurrentImage().equals("imageV2.jpg")) {
for (Rect rect : faceArea2Copy) {
BufferedImage facePart = bimage2.getSubimage(rect.x, rect.y, rect.width, rect.height);
g2d.drawImage(facePart, rect.x + 305, rect.y - 30,
rect.width + 295, rect.height + 325, this);
}
}
g2d.dispose();
}
repaint();
}
}
private void returnFace() {
if (originalBimage1 != null) {
// Restore the original image
bimage1 = deepCopy(originalBimage1);
faceArea1 = getArea(cascade, matFromBufferedImage(bimage1));
repaint();
}
}
public void paint(Graphics g) {
if (bimage1 != null) {
g.drawImage(bimage1, 10, 70, bimage1.getWidth() / 3, bimage1.getHeight() / 3, this);
}
if (bimage2 != null) {
g.drawImage(bimage2, 10, 400, bimage2.getWidth() / 2 - 60, bimage2.getHeight() / 2 - 10, this);
}
if (faceArea1 != null) {
g.setColor(Color.red);
for (Rect rect : faceArea1) {
g.drawRect((rect.x + 20) / 3, (rect.y + 60) / 2, rect.width / 3 + 10, rect.height / 3 + 20);
}
}
if (faceArea2 != null) {
faceArea.FaceAreas(g, faceArea2);
}
faceArea.Text(g, textArea);
}
private void detect() {
src1 = Imgcodecs.imread(FromCamera);
bimage1 = matToBufferedImage(src1);
originalBimage1 = deepCopy(bimage1); // Create a deep copy of the original image
faceArea1 = getArea(cascade, src1);
imageFiles = new ArrayList<>();
imageFiles.add("message.txt");
imageFiles.add("imageV1.jpg");
imageFiles.add("imageV2.jpg");
imageIterator = imageFiles.iterator();
loadNextImage();
}
private Rect[] getArea(String str, Mat src) {
Rect[] area = null;
CascadeClassifier faceDetector = new CascadeClassifier(path + str);
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(src, faceDetections);
area = faceDetections.toArray();
return area;
}
private BufferedImage matToBufferedImage(Mat matrix) {
int cols = matrix.cols();
int rows = matrix.rows();
int elemSize = (int) matrix.elemSize();
byte[] data = new byte[cols * rows * elemSize];
int type;
matrix.get(0, 0, data);
switch (matrix.channels()) {
case 1:
type = BufferedImage.TYPE_BYTE_GRAY;
break;
case 3:
type = BufferedImage.TYPE_3BYTE_BGR;
byte b;
for (int i = 0; i < data.length; i = i + 3) {
b = data[i];
data[i] = data[i + 2];
data[i + 2] = b;
}
break;
default:
return null;
}
BufferedImage out = new BufferedImage(cols, rows, type);
out.getRaster().setDataElements(0, 0, cols, rows, data);
return out;
}
private Mat matFromBufferedImage(BufferedImage image) {
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
mat.put(0, 0, data);
return mat;
}
private BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new PlayWithFace());
}
}
As mention above, I want button 2 to be replace to button 3 when it being clicked, and button 3 to be replace to button 2 when it being clicked.
I have tried many ways but I have no idea how to do it.
Please let me know if you need further information.