OpenCV, C ++ параллелизм, Windows

0

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

OBS: запуск в выпуске, но поворот оптимизаций с помощью /0d по-прежнему вызывает симптомы.

Симптомы: при вызове imshow ("blabla", изображение); на сервере мы получаем следующую ошибку: "Необработанное исключение в 0x54F26AF8 (opencv_highgui248d.dll) в файле newCVS2.exe: 0xC0000005: место чтения нарушения доступа 0x69577265". Однако, если мы делаем imwrite ("example.jpg", otherimage); прежде чем мы не получим эту ошибку. изображение и другое изображение - разные изображения. Мы пробовали пройти через код, никаких странных прыжков, которые я знаю.

В приведенном ниже коде найдите imwrite ("test.jpg", tmp3) с приведенным ниже кодом, мы получим ошибку, если imwrite будет раскоментирован, мы не будем. Я включил весь код для справки.

OBS: imwrite решает проблему, это не причина этого! Спасибо заранее, любые комментарии оценили.

Пример кода:

    // newCVS2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

#include <iostream>

#include <process.h>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


#pragma comment (lib, "Ws2_32.lib")

using namespace std;
using namespace cv;

void streamServer(void* arg);
void  quit(string msg, int retval);
int connect();

//HANDLE hMutex1;
Mat frame;
Mat img;

SOCKET ListenSocket;
SOCKET ClientSocket;
WSADATA wsaData;
int iResult;

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
int is_data_ready = 0;

HANDLE hMutex1 = CreateMutex( NULL, FALSE, NULL );

HANDLE syncMutex = CreateMutex( NULL, FALSE, NULL );


void streamServer(void* arg){

    int  imgSize = img.total()*img.elemSize();
    char* sockData = new char[imgSize];
    int  bytes=0;

    int errorMsg = connect();
    if(errorMsg != 0){
        cout << "error on: " << errorMsg;
    }

    SYSTEMTIME before;
    SYSTEMTIME after;

    // Receive until the peer shuts down the connection
    memset(sockData, 0x0, sizeof(sockData));
    do {
        GetSystemTime(&before);
        for(int i = 0; i < imgSize; i += iResult){
            iResult = recv(ClientSocket, sockData  + i, imgSize - i, 0);
            if(iResult == -1){
                printf("resv failed");
            }
        }

        GetSystemTime(&after);
        cout << (((after.wSecond * 1000) + after.wMilliseconds) - ((before.wSecond * 1000 ) + before.wMilliseconds)) << " time for recv \n";

        //int ptr = 0;
        GetSystemTime(&before);
        WaitForSingleObject( hMutex1, INFINITE );
                    for(int i = 0; i < img.rows; i++){
                        //row = sockData.part(
                        for(int j = 0; j < img.cols; j++){

                            (img.row(i)).col(j) = (uchar)sockData[((img.cols)*i)+j];
                            //img.at<cv::Vec3b>(i,j) = cv::Vec3b((uchar)sockData[ptr+ 0],(uchar)sockData[ptr+1],(uchar)sockData[ptr+2]);
                            //ptr = ptr + 3;
                        }
                    }

        cout << img.rows << " number of rows ";
        GetSystemTime(&after);

        is_data_ready = 1;
        memset(sockData, 0x0, sizeof(sockData));

        ReleaseMutex( hMutex1 );

        cout << (((after.wSecond * 1000) + after.wMilliseconds) - ((before.wSecond * 1000 ) + before.wMilliseconds)) << " time for annoying shit \n";

        if (iResult > 0) {
            printf("Bytes received: %d\n", iResult);
        }


        //Close the connection
        else if (iResult == 0)
            printf("Connection closing...\n");
        //Fail during connection
        else  {
            printf("recv failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
        }

    } while (iResult > 0);

    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
    }

    // cleanup
    closesocket(ClientSocket);
    WSACleanup();
}

int main()
{
    int width, height;
    width = 640;  
    height = 480; 
    img = Mat::zeros( height,width, CV_8UC1);



    is_data_ready = 0; // not needed



    _beginthread( streamServer, 0, NULL );
    //needed to make sure that server does not close
    while(true){
        WaitForSingleObject( hMutex1, INFINITE );
                if(is_data_ready){

                    cout << img.rows << " number rows before show \n";
                    cout << img.empty() << " empty? \n";



                    WaitForSingleObject( syncMutex, INFINITE );

                    Mat tmp0, tmp1, tmp2, tmp3, tmp4;

                    tmp4 = img;

                    bilateralFilter(img, tmp0, -1, 50, 5); 
                    Canny(tmp0, tmp1, 35, 200, 3); 

                    /*imwrite("test.jpg",tmp3);
                    waitKey(1);*/

                    ReleaseMutex( syncMutex );

                    WaitForSingleObject( syncMutex, INFINITE );

                    imshow("ServerWindow", tmp1);

                    ReleaseMutex( syncMutex );

                    waitKey(1);
                    cout << img.cols << " number cols after show \n";
                    is_data_ready = 0;
                }

        ReleaseMutex( hMutex1 );
        waitKey(1);
    }
    //connect();
    return 0;
}


void  quit(string msg, int retval){

}
int connect(){

    /*WSADATA wsaData;
    int iResult;

    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET ClientSocket = INVALID_SOCKET;

    struct addrinfo *result = NULL;
    struct addrinfo hints;

    int iSendResult;
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;*/


    struct addrinfo *result = NULL;
    struct addrinfo hints;

    ListenSocket = INVALID_SOCKET;
    ClientSocket = INVALID_SOCKET;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the server address and port
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Create a SOCKET for connecting to server
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }

    // Setup the TCP listening socket
    iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    freeaddrinfo(result);

    iResult = listen(ListenSocket, SOMAXCONN);
    if (iResult == SOCKET_ERROR) {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // No longer need server socket
    closesocket(ListenSocket);
    return 0;
}

Изменение: если добавить тест, если tmp1 пуст, как было предложено, я получаю другое исключение:

bilateralFilter(img, tmp0, -1, 50, 5); 
                    Canny(tmp0, tmp1, 35, 200, 3); 
                    //ytp = frame;
                    //testImage = frame;

                    imwrite("test.jpg",tmp3);
                    waitKey(1);

                    waitKey(500);
                    ReleaseMutex( syncMutex );

                    WaitForSingleObject( syncMutex, INFINITE );

                    if (tmp1.empty()) { 
                        std::cout << "tmp1 is empty" << std::endl; 
                        break;
                    }
                    imshow("ServerWindow", tmp1);

программа теперь вылетает на imwrite и выдает исключение: Необработанное исключение в 0x67BDFF1F (msvcr110d.dll) в файле newCVS2.exe: 0xC0000005: Место для чтения нарушения доступа 0x67706A2E.

это заставляет меня думать, что есть некоторые проблемы с доступом к матам

Теги:
opencv
multithreading

2 ответа

1
  • Проверьте, не является ли tmp1 пустым, например

    if (tmp1.empty) { 
        std::cout << "tmp1 is empty" << std::endl; 
        break;
    }
    
  • Я заметил, что функция imshow не является потокобезопасной (по крайней мере, на Windows-машине). Например, если я вызову imshow из двух разных потоков, моя программа будет раздавлена. Программа также будет раздавлена, если я namedWindow() команду namedWindow() в одном потоке, а затем imshow() в другом потоке. Поэтому убедитесь, что вы этого не делаете. Как замечание, лучше создать окно вывода с помощью namedWindow("ServerWindow"), прежде чем вызывать imshow. Создайте это окно только один раз (вне цикла for) и в том же потоке, где вы вызываете imshow. Это улучшит производительность и может решить проблему.

  • 0
    Спасибо за хороший комментарий. Я попытался добавить строку tmp1.empty, теперь программа аварийно завершает работу и выдает исключение: необработанное исключение в 0x67BDFF1F (msvcr110d.dll) в newCVS2.exe: 0xC0000005: расположение чтения нарушения доступа 0x67706A2E. Программа вылетает на строке imwrite. Что супер странно. Я обновил основной пост с информацией
  • 0
    Кроме того, если я на самом деле вызываю: namedWindow ("ServerWindow", CV_WINDOW_AUTOSIZE); Я получаю исключение: необработанное исключение в 0x66796AF8 (opencv_highgui248d.dll) в newCVS2.exe: 0xC0000005: расположение чтения нарушения доступа 0x69577265. На этой линии
Показать ещё 2 комментария
0

Это потому, что tmp3 только инициализирован, он не имеет никаких данных. Попытка написать tmp0 или tmp1 будет работать в этом коде.

  • 0
    Вы неправильно поняли, imwrite не вызывает проблемы, использование imwrite устраняет проблему. Причина, по которой у нас пустой tmp3, заключается в сокращении времени, необходимого для сохранения изображения. Программа аварийно завершает работу на imshow только в том случае, если раньше мы не делали imwrite. пишу tmp0, tmp1 tmp3 все отлично работает, это когда я ничего не пишу. Хаха, я вижу, что это сбивает с толку, но не знаю, как сформулировать лучше: P
  • 0
    Вы пытались использовать waitkey (500) в области, где используется imwrite? (оставив комментарий закомментированным)
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню