Вернитесь к основному после завершения потока

#java #multithreading

Вопрос:

В настоящее время я возюсь с распознаванием лиц и пытаюсь делать фотографии с помощью своей веб-камеры. Я адаптирую этот учебник для автоматического присвоения имени и сохранения сделанного снимка. Обратите внимание, что этот код вызывается из функции main (), которая сама по себе реализована в другом классе. До тех пор, пока я не остановлю поток с помощью interrupt (), он работает. После этого изображение застывает в графическом интерфейсе, и система, похоже, не возвращается в класс, в котором я работаю над своим графическим интерфейсом.
Чтобы внести ясность: я хочу сделать снимок с моей веб-камеры и заменить прежний поток с моей веб-камеры указанным ранее снятым изображением. До тех пор, пока я не сделаю снимок и не прерву поток, код работает. В кормовой части он застрял.
Я попробовал вставить нить в список действий CaptureButton, но это не удалось, потому что основной элемент графического интерфейса был недоступен, что является курьезным, учитывая, что он определен как общедоступный. Однако в ходе компиляции он выдает некоторые предупреждения, хотя я должен признать, что понятия не имею, что они означают:

 [ WARN:0] global C:buildmaster_winpack-bindings-win64-vc14-staticopencvmodulesvideoiosrccap_msmf.cpp (376) `anonymous-namespace'::SourceReaderCB::OnReadSample videoio(MSMF): OnReadSample() is called with error status: -1072873821
[ WARN:0] global C:buildmaster_winpack-bindings-win64-vc14-staticopencvmodulesvideoiosrccap_msmf.cpp (388) `anonymous-namespace'::SourceReaderCB::OnReadSample videoio(MSMF): async ReadSample() call is failed with error status: -1072873821
[ WARN:1] global C:buildmaster_winpack-bindings-win64-vc14-staticopencvmodulesvideoiosrccap_msmf.cpp (1021) CvCapture_MSMF::grabFrame videoio(MSMF): can't grab frame. Error: -1072873821
Exception in thread "Thread-0" CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.5.2) C:buildmaster_winpack-bindings-win64-vc14-staticopencvmodulesimgcodecssrcloadsave.cpp:896: error: (-215:Assertion failed) !image.empty() in function 'cv::imencode'
]
    at org.opencv.imgcodecs.Imgcodecs.imencode_1(Native Method)
    at org.opencv.imgcodecs.Imgcodecs.imencode(Imgcodecs.java:510)
    at GUI.FaceRecognition.startCamera(FaceRecognition.java:129)
    at main$1$1.run(main.java:19)
    at java.base/java.lang.Thread.run(Thread.java:834)
[ WARN:2] global C:buildmaster_winpack-bindings-win64-vc14-staticopencvmodulesvideoiosrccap_msmf.cpp (438) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
Thread vorbei
 

Я написал свой код довольно дилетантски в этом, я уверен, и я думаю, что мог бы использовать что-то вроде callable (), но не уверен, кто это использует. Я также не знаю, как воспроизвести свою проблему за пределами распространения всего моего проекта по Интернету, но, тем не менее, я могу предоставить код своих изменений:

  • для самой функции
 public boolean startCamera(){
       capture= new VideoCapture(0);
       image=new Mat();
       byte[] imageData;
       ImageIcon icon;
       String name = null;
       boolean echo = false;
       while(true){
           capture.read(image);
           final MatOfByte buf=new MatOfByte();
           Imgcodecs.imencode(".png", image,buf);
           imageData= buf.toArray();
           icon=new ImageIcon(imageData);
           Feed.setIcon(icon);
           if(trigger==true){
               name="Recognition";
               Imgcodecs.imwrite("src/" name ".png",image);
               trigger=false; //Auslöser zurücksetzten
           }
           File kamera=new File("src/Recognition.png");
           if(kamera.exists()==true){
               //capture.release();
               /*try {
                   Kamera=ImageIO.read(this.getClass().getResourceAsStream("/Recognition.png"));
               } catch (IOException e) {
                   e.printStackTrace();
               }*/
               return echo=true;
           }
       }
   }
 
  • для главного()
 import java.awt.*;
import java.io.File;
import java.lang.String;
import GUI.*;
import org.opencv.core.Core;


public class main {
public static void main(String[] args){
    FaceRecognition Fenster=new FaceRecognition();
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            //FaceRecognition Fenster=new FaceRecognition();
            new Thread (new Runnable() {
                @Override
                public void run() {
                    Fenster.startCamera();
                }
            }).start();
            //File kamera=new File(("src/Recognition.png"));

        }
    });
    if(Fenster.startCamera()==true){
        Thread.currentThread().interrupt();
        System.out.println("Thread vorbei");
    }

}
}
 

Please point out where I went wrong or what goes wrong.

Edit:
I have mean while heeded @pveentjers advice and reformed my code (see below). Yet in my main() the IDE proposes to make startCamera static which will not work because startCamera can not be static (or rather elements of it can’t). Is there any way to move around this?

  • the startCamera function
 public class startCamera implements Runnable{
        private CountDownLatch end;

        public startCamera(CountDownLatch one){
            this.end=one;
           }
        @Override public void run(){
            try {
                capture= new VideoCapture(0);
                image=new Mat();
                byte[] imageData;
                ImageIcon icon;
                String name = null;
                while(true){
                    capture.read(image);
                    final MatOfByte buf=new MatOfByte();
                    Imgcodecs.imencode(".png", image,buf);
                    imageData= buf.toArray();
                    icon=new ImageIcon(imageData);
                    Feed.setIcon(icon);
                    if(trigger==true){
                        name="Recognition";
                        Imgcodecs.imwrite("src/" name ".png",image);
                        trigger=false; //Auslöser zurücksetzten
                    }
                    File kamera=new File("src/Recognition.png");
                    if(kamera.exists()==true){
                        capture.release();
                        end.countDown();
                /*try {
                    Kamera=ImageIO.read(this.getClass().getResourceAsStream("/Recognition.png"));
                } catch (IOException e) {
                    e.printStackTrace();
                }*/

                    }
                }
            }
            catch (Exception exception){

            }

        }
 
  • реформированный главный()
 import java.awt.*;
import java.io.File;
import java.lang.String;
import java.util.concurrent.CountDownLatch;

import GUI.*;
import GUI.FaceRecognition.startCamera;
import org.opencv.core.Core;


public class main {
public static void main(String[] args){
    FaceRecognition Fenster=new FaceRecognition();
    CountDownLatch mark=new CountDownLatch(1);
    startCamera startCamera=new startCamera(mark);
    try {
       mark.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
 

Может быть, я не делаю дерево для деревьев, но это первый раз, когда я работаю с нитями.

Комментарии:

1. Вы могли бы создать обратный отсчет(1) в главном потоке и передать его на запускаемый и по завершении сделать отсчет времени. В вашем основном потоке сделайте защелку.ждите(); Это заставит основной поток синхронизироваться по завершении выполняемого. Я не очень внимательно изучил ваш код, запуск нового потока из запроса событий выглядит немного пугающе.

2. Спасибо. Я подумал, что это может выглядеть странно, потому что я скопировал код из учебника в свой базовый графический интерфейс и попытался там работать. Знаете ли вы ресурс для абсолютных новичков в потоках?

3. У Oracle есть учебник по rad, создающий графический интерфейс с помощью Swing . Пропустите раздел Netbeans. Раздел, посвященный потокам, называется параллелизмом в Swing .