Czy istnieje implementacja metody podziału i scalania segmentacji obrazu? każda rada byłaby mile widziana.Segmentacja obrazu - Split and Merge (Quadtrees)
Odpowiedz
O czym jest segmentacja?
Segmentacja oznacza podział obrazu na kilka połączonych regionów. Zasadniczo można dokonać segmentacji z dwiema definicjami regionu: można zdefiniować region jako grupę połączonych podobnych pikseli lub zbiór połączonych pikseli otoczony nieciągłościami (krawędziami). Podziel i scalaj używa pierwszego podejścia.
Matematycznie rzecz biorąc: jeśli cały obraz jest reprezentowany przez zbiór pikseli (zwanych R), niż chcieliby Państwo uzyskać podzbiory takie jak
- Segmentacja jest kompletna, więc wszystkie podregiony sumują się do całości R. Związek wszystkich regionów: R UR U ... n UR = R.
- R i jest podłączony.
- Regiony są różne. R i ∩ R j = ∅ podano, że ≠ j
- Regiony mają podobne właściwości. Można to wyrazić za pomocą funkcji zwanej kryterium homogeniczności (P). Powinien dawać PRAWDZIWOŚĆ członkom danego regionu i FALSE dla wszystkich pozostałych regionów.
- Nie można scalić regionów sąsiadujących. Dla wszystkich regionów P (R i U R j) = FALSE, biorąc pod uwagę, że i ≠ j.
Co to jest algorytm podziału i scalania?
Po pierwsze, musimy wybrać kryterium homogeniczności. Kryterium jednorodności może mieć charakter globalny (w zależności od regionu) lub lokalny (w zależności od niewielkiego okna regionu, a jeśli jest prawdziwe dla wszystkich okien, niż w przypadku regionu). Prostym przykładem może być odchylenie od średniej powinno być mniejsze niż próg. & all; p i ∈ R i: | p i - μ | ≤ f * σ.
Algorytm podziału i scalania składa się z dwóch faz: podziału i fazy scalania. W fazie podziału rekursywnie dzielimy regiony na cztery podregiony (zaczynając od całego obrazu jako jednego regionu), dopóki nasze kryterium homogeniczności nie zostanie spełnione we wszystkich podregionach. Łatwo zauważyć, że warunki 1-4 segmentacji są spełnione. Przechodzimy do etapu scalania w celu spełnienia warunku 5th.
W etapie łączenia się sprawdzić, że P (R i U R J) = TRUE każdych dwóch sąsiednich obszarów, i połączenie dwóch regionów. Powtarzamy ten krok, dopóki nie będą potrzebne żadne zmiany. Teraz spełniliśmy wszystkie warunki, nasz obraz został podzielony na podregiony.
Pseudokod
Oto pseudokod do dzielenia i łączenia algorytmu:
- Init: mamy tylko jeden duży obszar (cały obraz).
- Podział: Jeśli P (R i) = PRAWDA przejdź do następnego kroku. W przeciwnym razie podziel część R i na cztery podregiony i wykonaj na nich krok 2.
- Scal, gdy: R i R J sąsiadują i P (R i UR J) = PRAWDA, połączenie dwóch regionów niż powtarzania etapu 3. Jeżeli nie ma takich regionów jesteśmy skończone.
algorytm segmentacji split-seryjnej został wdrożony tutaj: http://www.uni-koblenz.de/~lb/lb_downloads
To moja realizacja. Nie jestem guru C++/opencv, więc jeśli ktoś znajdzie jakiś sposób na zoptymalizowanie tego skryptu, dodaj komentarze!
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat img;
Size size;
struct region {
// tree data structure
vector<region> childs;
bool validity; // TODO: have a method for clear the data structure and remove regions with false validity
// tree for split&merge procedure
Rect roi;
Mat m;
Scalar label;
Mat mask; // for debug. don't use in real cases because it is computationally too heavy.
};
//----------------------------------------------------------------------------------------------------------------------- merging
bool mergeTwoRegion(region& parent, const Mat& src, region& r1, region& r2, bool (*predicate)(const Mat&)) {
if(r1.childs.size()==0 && r2.childs.size()==0) {
Rect roi1 = r1.roi;
Rect roi2 = r2.roi;
Rect roi12 = roi1 | roi2;
if(predicate(src(roi12))) {
r1.roi = roi12;
// recompute mask
r1.mask = Mat::zeros(size, CV_8U);
rectangle(r1.mask, r1.roi, 1, CV_FILLED);
r2.validity = false;
return true;
}
}
return false;
}
void merge(const Mat& src, region& r, bool (*predicate)(const Mat&)) {
// check for adjiacent regions. if predicate is true, then merge.
// the problem is to check for adjiacent regions.. one way can be:
// check merging for rows. if neither rows can be merged.. check for cols.
bool row1=false, row2=false, col1=false, col2=false;
if(r.childs.size()<1) return;
// try with the row
row1 = mergeTwoRegion(r, src, r.childs[0], r.childs[1], predicate);
row2 = mergeTwoRegion(r, src, r.childs[2], r.childs[3], predicate);
if(!(row1 | row2)) {
// try with column
col1 = mergeTwoRegion(r, src, r.childs[0], r.childs[2], predicate);
col2 = mergeTwoRegion(r, src, r.childs[1], r.childs[3], predicate);
}
for(int i=0; i<r.childs.size(); i++) {
if(r.childs[i].childs.size()>0)
merge(src, r.childs[i], predicate);
}
}
//----------------------------------------------------------------------------------------------------------------------- quadtree splitting
region split(const Mat& src, Rect roi, bool (*predicate)(const Mat&)) {
vector<region> childs;
region r;
r.roi = roi;
r.m = src;
r.mask = Mat::zeros(size, CV_8U);
rectangle(r.mask, r.roi, 1, CV_FILLED);
r.validity = true;
bool b = predicate(src);
if(b) {
Scalar mean, s;
meanStdDev(src, mean, s);
r.label = mean;
} else {
int w = src.cols/2;
int h = src.rows/2;
region r1 = split(src(Rect(0,0, w,h)), Rect(roi.x, roi.y, w,h), predicate);
region r2 = split(src(Rect(w,0, w,h)), Rect(roi.x+w, roi.y, w,h), predicate);
region r3 = split(src(Rect(0,h, w,h)), Rect(roi.x, roi.y+h, w,h), predicate);
region r4 = split(src(Rect(w,h, w,h)), Rect(roi.x+w, roi.y+h, w,h), predicate);
r.childs.push_back(r1);
r.childs.push_back(r2);
r.childs.push_back(r3);
r.childs.push_back(r4);
}
//merge(img, r, predicate);
return r;
}
//----------------------------------------------------------------------------------------------------------------------- tree traversing utility
void print_region(region r) {
if(r.validity==true && r.childs.size()==0) {
cout << r.mask << " at " << r.roi.x << "-" << r.roi.y << endl;
cout << r.childs.size() << endl;
cout << "---" << endl;
}
for(int i=0; i<r.childs.size(); i++) {
print_region(r.childs[i]);
}
}
void draw_rect(Mat& imgRect, region r) {
if(r.validity==true && r.childs.size()==0)
rectangle(imgRect, r.roi, 50, .1);
for(int i=0; i<r.childs.size(); i++) {
draw_rect(imgRect, r.childs[i]);
}
}
void draw_region(Mat& img, region r) {
if(r.validity==true && r.childs.size()==0)
rectangle(img, r.roi, r.label, CV_FILLED);
for(int i=0; i<r.childs.size(); i++) {
draw_region(img, r.childs[i]);
}
}
//----------------------------------------------------------------------------------------------------------------------- split&merge test predicates
bool predicateStdZero(const Mat& src) {
Scalar stddev, mean;
meanStdDev(src, mean, stddev);
return stddev[0]==0;
}
bool predicateStd5(const Mat& src) {
Scalar stddev, mean;
meanStdDev(src, mean, stddev);
return (stddev[0]<=5.8) || (src.rows*src.cols<=25);
}
//----------------------------------------------------------------------------------------------------------------------- main
int main(int /*argc*/, char** /*argv*/)
{
img = (Mat_<uchar>(4,4) << 0,0,1,1,
1,1,1,1,
3,3,3,3,
3,4,4,3);
cout << img << endl;
size = img.size();
region r;
r = split(img, Rect(0,0,img.cols,img.rows), &predicateStdZero);
merge(img, r, &predicateStdZero);
cout << "------- print" << endl;
print_region(r);
cout << "-----------------------" << endl;
img = imread("lena.jpg", 0);
// round (down) to the nearest power of 2 .. quadtree dimension is a pow of 2.
int exponent = log(min(img.cols, img.rows))/log (2);
int s = pow(2.0, (double)exponent);
Rect square = Rect(0,0, s,s);
img = img(square).clone();
namedWindow("original", CV_WINDOW_AUTOSIZE);
imshow("original", img);
cout << "now try to split.." << endl;
r = split(img, Rect(0,0,img.cols,img.rows), predicateStd5);
cout << "splitted" << endl;
Mat imgRect = img.clone();
draw_rect(imgRect, r);
namedWindow("split", CV_WINDOW_AUTOSIZE);
imshow("split", imgRect);
imwrite("split.jpg", imgRect);
merge(img, r, &predicateStd5);
Mat imgMerge = img.clone();
draw_rect(imgMerge, r);
namedWindow("merge", CV_WINDOW_AUTOSIZE);
imshow("merge", imgMerge);
imwrite("merge.jpg", imgMerge);
Mat imgSegmented = img.clone();
draw_region(imgSegmented, r);
namedWindow("segmented", CV_WINDOW_AUTOSIZE);
imshow("segmented", imgSegmented);
imwrite("segmented.jpg", imgSegmented);
while(true)
{
char c = (char)waitKey(10);
if(c == 27) { break; }
}
return 0;
}
Jeśli dobrze rozumiem, że implementacja łączenia nie spełnia wymogu, że "regiony sąsiadujące z przestrzenią obrazu mogą mieć różnych rodziców lub znajdować się na różnych poziomach (tj. Różnej wielkości) w strukturze piramidalnej", która jest opisana [tutaj] (http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MARBLE/medium/segment/split.htm). Jest to jednak ważne i powinniśmy być tego świadomi. –
- 1. Segmentacja obrazu dla iOS
- 2. Segmentacja obrazu w skali szarości
- 3. Split FirstName and LastName w sqlite
- 4. obrazu (kolor?) Segmentacja z OpenCV C++
- 5. Wykrywanie i segmentacja krawędzi
- 6. Trudna segmentacja obrazu: tło i obiekty są podobne
- 7. HHVM RepoMode Segmentacja Fault
- 8. Segmentacja wina - char wskaźnik
- 9. Segmentacja na vprintf.c
- 10. C++ Błąd podstawowy Program segmentacja
- 11. Image Processing - Dress Segmentacja za pomocą OpenCV
- 12. Zakres dat SQL Split
- 13. split data.table
- 14. Split ikiki
- 15. Malloc, wolny i segmentacja winy
- 16. Segmentacja gestów w systemie Android
- 17. OSX Segmentacja Błąd 11 - Android
- 18. Perl Split i wyrażenie regularne
- 19. intellij: Split pionowo skrót klawiaturowy?
- 20. Czy są jakieś przykłady quadtrees używane w Canvas HTML5?
- 21. MERGE Naruszenie klucz podstawowy
- 22. onScale and Canvas - jak ustawić punkt początkowy po powiększeniu obrazu?
- 23. Split XML w PHP
- 24. Split wynik „licznik”
- 25. IntelliJ Split Window Navigation
- 26. split ("\\") i błąd
- 27. F # Funkcja Split
- 28. split string with regex
- 29. C# string split
- 30. Dlaczego "////'.split('/") produkuje []?
Szukam wdrożenia algorytmu, moim ideałem byłoby C# ale mogę konwertować z innych języków. czy przypadkiem znasz gdzieś dobry kod? – Medosopher