Funkcja dopasowująca szablon się zawiesza

Funkcja dopasowująca szablon się zawiesza
XP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 157
0

W AI napisałem to zapytanie
template matching po polsku zwraca x y program c++ bez biblioteki opencv bez c++11 wczytaj obrazy jpg

otrzymałem prosty kod

Kopiuj
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include <iostream>
#include <climits>

// Funkcja obliczająca dopasowanie metodą sumy kwadratów różnic (SSD)
void findTemplate(const unsigned char* img, int imgW, int imgH,
                  const unsigned char* tmpl, int tmplW, int tmplH,
                  int& outX, int& outY) {
    long long minDiff = LLONG_MAX;
    outX = 0;
    outY = 0;

    for (int y = 0; y <= imgH - tmplH; ++y) {
        for (int x = 0; x <= imgW - tmplW; ++x) {
            long long currentDiff = 0;

            for (int ty = 0; ty < tmplH; ++ty) {
                for (int tx = 0; tx < tmplW; ++tx) {
                    int imgIdx = ((y + ty) * imgW + (x + tx)) * 3;
                    int tmplIdx = (ty * tmplW + tx) * 3;

                    // Suma różnic dla kanałów RGB
                    for (int c = 0; c < 3; ++c) {
                        long long diff = img[imgIdx + c] - tmpl[tmplIdx + c];
                        currentDiff += diff * diff;
                    }
                }
            }

            if (currentDiff < minDiff) {
                minDiff = currentDiff;
                outX = x;
                outY = y;
            }
        }
    }
}

int main() {
    int imgW, imgH, imgChannels;
    int tmplW, tmplH, tmplChannels;

    // Wczytywanie obrazów JPG
    unsigned char* imgData = stbi_load("obraz.jpg", &imgW, &imgH, &imgChannels, 3);
    unsigned char* tmplData = stbi_load("szablon.jpg", &tmplW, &tmplH, &tmplChannels, 3);

    if (!imgData || !tmplData) {
        std::cout << "Blad wczytywania obrazow!" << std::endl;
        return 1;
    }

	std::cout << "Wymiary obrazu glownego: " << imgW << "x" << imgH << " px" << std::endl;
	std::cout << "Wymiary szablonu: " << tmplW << "x" << tmplH << " px" << std::endl;
    int bestX = 0, bestY = 0;
    findTemplate(imgData, imgW, imgH, tmplData, tmplW, tmplH, bestX, bestY);

    std::cout << "Znaleziono wspolrzedne -> X: " << bestX << ", Y: " << bestY << std::endl;

    stbi_image_free(imgData);
    stbi_image_free(tmplData);
    return 0;
}
i funkcja findTemplate() się zawiesza i nie wiem, gdzie jest błąd. Czy możecie pomóc?
Marius.Maximus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2267
2

Autor kodu jest odpowiedzialny za swój kod: Zapytaj AI
A nie ma lepszych algorytmów dla tego problemu ?

XP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 157
0
Marius.Maximus napisał(a)

A nie ma lepszych algorytmów dla tego problemu ?

Jeśli są lepsze algorytmy bez biblioteki OpenCV i bez C++ 11, to proszę o podanie

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5687
2

ale skąd w ogóle pewność że program się wiesza? na oko nie widać nieskończonych pętli tylko pętle z licznikiem. uruchom ten progam ja jakimś małym orazku 10 x10 albo 100 na 100 a nie 4k

Update chat gpt mówi mi iż złożonośc tego to O(imgW⋅imgH⋅tmplW⋅tmplH) no to to jest w ... dużo i jeszcze trochę

Update 2 drugim rozwiązaniem jest dodanie jakiegokolwiek loga na stdout w jakim stanie aktualnie znajduje się program.w której pętli i co robi. Trzecie to odpalenie tego w debugerze, ale nawet jeszcze niewiesz gdzie szukasz więc prymitywny log może być lepszy. tylko nie za często bo logowanie zajmie więcej czasu niż inne obliczenia

Update 3 zgaduję iż biblioteki robią to szybko bo liczą na karcie graficznej albo chociaż na procesorze ale z wektorowymi instrukcjami równoległymi a ty to robicz totalnie jekwencyjnie w jednym wątku na jednym korze w jednym procesorze. Ale to tylko takie sa pisanie palcem na wodzie bo sam nigdy nie przerzucałem obliczen na kartę graficzną

XP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 157
0
KamilAdam napisał(a):

ale skąd w ogóle pewność że program się wiesza? na oko nie widać nieskończonych pętli tylko pętle z licznikiem. uruchom ten progam ja jakimś małym orazku 10 x10 albo 100 na 100 a nie 4k

Masz racje - zrobiłem dla małych obrazków i rzeczywiście działa, tylko potrzebuje dużo czasu

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
2

Pytanie też jak to zbudowałeś i czym?
Parę flag kompilatora i ten kod może dramatycznie przyspieszyć.

Z tego co sprawdziłem przy odpowiednich ustawieniach:

  • gcc i clang ładnie wektoryzują kod i używą SIMD.
  • MSVC niestety w tym przypadku zawodzi:
XP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 157
0

A czy jest jakaś strona, która online zwróci mi x i y miejsca, w którym na dużym obrazie zaczyna się mały obraz? Strona https://pixlane.media/pl-pl/template-matching/ rysuje obwolutę, ale nie zwraca danych punktu - oczywiście można skopiować do Paint i po najechaniu myszką odczytać, ale zawsze powoduje to margines błędu

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
3

Tylko skompilowałem Dev C++ - jeśli wiesz, jak przyspieszyć, to proszę o pomoc

Dev C++ to jest tylko IDE (zintegrowane środowisko programistyczne) - coś co łączy do kupy: edytor tekstu, kompilator, linker, debugger i inne narzędzia.
Pod spodem Dev C++ używa gcc (przeniesione na Windows jako MinGW).

Gdzieś tam w opcjach Dev C++ można dodać wymagane flagi. Masz dodać

  • -O3
  • -march=skylake albo -march=native (używaj architektury obecnej maszyny).

Nie użyam Dev C++, więc nie wskażę ci dokładnego miejsca, ale nie powinno yć to trudne.


Z tego co widzę:

Dev-C++ 5.0 (4.9.9.2) with Mingw/GCC 3.4.2 compiler and GDB

Dev-C++ 5.0 używa bardzo starej wersji GCC 3.4.2, które zostało opublikowane w 2004!
Ergo nie zrozumie co to jest skylake :/.

brokenelevator
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 62
2

Czy możesz napisać trochę więcej o ograniczeniach projektu?

  • Dlaczego bez OpenCV?
  • Dlaczego bez C++11 (lub nowszego)?
  • Dlaczego używasz Dev-C++?

Czy te ograniczenia wynikają z własnego wyboru? Są narzucone przez kurs, książkę albo prowadzącego?

Jeśli nie jesteś związany z Dev-C++, to polecałbym przesiadkę na nowszy standard, np. C++17 lub C++20, oraz zmianę środowiska na Code::Blocks z aktualnym GCC/MinGW-w64. Nadal jest proste w obsłudze, a zapewnia dostęp do współczesnego C++ oraz lepszych narzędzi diagnostycznych.

Dev-C++ od lat praktycznie nie jest rozwijany i obecnie potrafi bardziej przeszkadzać niż pomagać.

Marius.Maximus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2267
0

Mam wrażenie że OP podchodzi do problemu z najgorszej możliwych stron,
skoro w komentarzach pojawia się uwaga "od zawsze używałem Dev C++ i nie mogłem połączyć z OpenCV"
to lepiej zając się prawdziwym problemem ?

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.