Képfeldolgozás Képi információk kinyerése Fényképek minőségének javítása
. A Bitképek a programokban..net Bitképek a Bitmap.. A.Net... Image Class (managed C++)...Net Bitképek a Bitmap Class... Konstruktorok... Tulajdonságok...3 Metódusok...4 Bitképek módosítása a GetPixel() és SetPixel() lassú...5 Bitképek gyors módosítása...5. A bitkép adatainak rögzítése...5. A bitkép bitjeinek áttöltése a menedzselt és nem menedzselt memóriák közt...5.3 Módosítás a nem menedzselt memóriában...5.4 Visszatöltés a nem menedzselt memóriából a menedzselt memóriába...5.5 A bitkép rögzítésének megszüntetése. Open CV Computer Vision library.. Az OpenCV telepítése... Az OpenCV a Visual Studio-ban.. Az OpenCV ablakozása..3 OpenCV Mat..3. Az OpenCV Mat osztály..3.. Konstruktorok..3.. Kifejezések (metódusok)..3..3 Egyéb metódusok
..4 Képek rögzítése. beolvasása, megjelenítése, kiírása..5 Video beolvasása a VideoCapture osztály..5. Konstruktorok..5. Metódusok..5.. Kamera olvasása..5.. Video file olvasása..6 Video file írása a VideoWriter osztály..6. Konstruktorok..6. Metódusok..6.3 Felvevő..7 A képtípus konvertálása..8 Színfényesség-hisztogramm..8. Színsíkok szétvágása..8. A hisztogramm(ok) számítása..8.3 A tömbök - hisztogramm(ok) normalizálása..9 Képhibák javítása..9. Konvolúció..9. Elmosás/Blur..9.3 Gauss-elmosás - GaussianBlur..9.4 Medián szűrés.. Élkeresés... A változás sebességének vizsgálata (Gradiens)... Sobel módszere... Élkeresés a változás gyorsulása alapján (Laplace)...3 Élkeresés a Canny módszerével 3
.. Képek élesítése... Csúszka... Élesítő konvolúció (filterd)...3 Éles kép=.5*kép-.5*blur(kép)...4 Zajcsökkentő élkiemelés.. Szegmentálás... Globális szegmentálás küszöbértékekkel ( )... Az Isodata algoritmus ( )... Otsu módszerének matematikai megfogalmazása ( )... Adaptív (lokális) szegmentálás küszöbértékekkel ( )... Küszöbérték lokális hisztogram alapján ( )...3 Részhalmazokra bontás fuzzy logikával ( )...4 Elárasztás ( )...4. Elárasztás statisztikával ( )...5 Szegmentálás tartományokkal ( )...5. Vágás és egyesítés...5. Csoportosítások...5.. Klaszterezés...5.. K-means algoritmus..3 Alakfelismerés..3. Alakfelismerés sablonillesztéssel..3. Alakfelismerés Hough transzformációval..3.. Egyenesek..3.. Körök..3.3 Előtér, háttér grabcut algoritmus 4
Képek információinak feldolgozása (3D). Pozíció-meghatározás síkban.. A sík-sík perspektíva bijekció. Kalibráció.3 Kontúrok keresése 3 A térlátás 3. Intrinsic paraméterek 3. Extrinsic paraméterek 3.3 Epipoláris geometria 5
. A Bitképek a programokban Képi adatok leírása Vektoros Raszteres Meta Színek, színmodellek CDR BMP, DIB, JPG True Type, WYSWYG, WMF, EMF -3 millió pálcika a világosság 5-7 millió csap a színes látás (érzékenyebb) A csapoknak érzékenységük szerint három csoportja van: L-, M- és S-típusú csapok (long, medium, short),. L - a fény intenzitása r L( ) x( ) d g L( ) y( ) d b L( ) z( ) d λ -Hullámhossz RedGreenBlue CyanMagentaYellow LightnessHueSaturance 6
Szín definíció fekete fehér (,) szürke árnyalat (..55) színes paletta index RGB RGBA HLS 7
HLS-színmodell H a színárnyalatra (hue), L a fényességre (lightness), S pedig a telítettségre (saturation) utal. RGB HSL.) r = R, g = G, b = B R max G max B max.) min = min r, g, b, max = max(r, g, b) 3.) L = min+max, ha min = max, szürke kép 4.) S = max min, egyébként + L 5.) H =, ha min = max g b max min, ( + b r max min ), (4 + r g max min ), ha max = r ha max = g ha max = b 8
HSL RGB if (L <=.5) M = L *( + S); else M = L + S - L * S; M = * L - M; if (S == ) R = G = B = L ; // R,G,B else h = H + ; if (h > 36) h = h 36; if (h < 6) R = ( M + ( M - M ) * h / 6); // R else if (h < 8) R = M; // R else if (h < 4) R = M + ( M - M ) * ( 4 - h ) / 6; // R else R = M; // R h = H; if (h < 6) G = ( M + ( M - M ) * h / 6; // G else if (h < 8) G = M; // G else if (h < 4) G = M + ( M - M ) * ( 4 - h ) / 6; // G else G = M; // G h = H ; if (h < ) h += 36 if (h < 6) B = ( M + ( M - M ) * h / 6; // B else if (h < 8) B = M; // B else if (h < 4) B = M + ( M - M ) * ( 4 - h ) / 6; // B else B = M; // B 9
Képek tárolása fontosabb fájlformátumok BMP A memória formátum (DIB device independent). JPEG Veszteséges tömörítés, minőségromlás, az egyik legelterjedtebb (MPEG). GIF PNG Maximum 56 különféle színből álló kép, kihalóban (animált GIF). Egyesíti a JPEG és a GIF előnyeit. Készíthető vele GIF-szerű, kevés különböző színből álló kép, JPEG-hez hasonló akár 6 millió különböző színárnyalatot tartalmazó kép is, A kép tartalmazhat átlátszóságot biztosító ún. alfa csatornát is. RAW Nyers kép a fényképezőgépek saját az érzékelőből kiolvasott, adatokat minimálisan feldolgozott formában tartalmazó fájlformátuma.
. GIMP..Net Bitképek a Bitmap bitkép mérettel, formátummal Format6bppGrayScale Format4bppRgb Format3bppARgb Format64bppARgb Indexed - 6 bit per pixel 65536 árnyalat - 4(3-ből) bit per pixel nem_ használt_r_g_b - 3 bit per pixel alpha_r_g_b - 64 bit per pixel alpha_r_g_b - Színindex (paletta)
.. A.Net... Image Class (managed C++) Image absztrakt képtároló - ős System::Drawing::Bitmap raszteres System::Drawing::Imaging::MetaFile vektoros Tagfüggvények static int GetPixelFormatSize(PixelFormat pixfmt); return: A színmélység bitekben pixfmt: BitMap tulajdonság Gdi Alpha Format8bppIndexed GDI színkód (rgb) áttetszőség index, 8 bit/ (56) szín. static bool IsAlphaPixelFormat(PixelFormat pixfmt); áttetsző? static bool IsCanonicalPixelFormat( PixelFormat pixfmt); 3 bites? static bool IsExtendedPixelFormat(
...Net Bitképek a Bitmap Class using namespace System::Drawing::Bitmap;... Konstruktorok Bitmap(String) Bitmap(String, Boolean) Az Image leszármazottja bitkép a file-ból (BMP, GIF, EXIF, JPG, PNG, TIFF lehet a kiterjesztés) bitkép a file-ból, van e színkorrekció Bitmap(Int3, Int3) bitkép mérettel Bitmap(Int3, Int3, PixelFormat) bitkép mérettel, formátummal, volt... Tulajdonságok Height - magasság HorizontalResolution- felbontás pixel/inch VerticalResolution - felbontás pixel/inch Width - szélesség PixelFormat - formátum...3 Metódusok Gdi Alpha FormatbppIndexed Format3bppRgbSpecifies a pixelekben GDI színek AlphaRGB bit per pixel és színindex 3 bit per pixel nem_ használt_r_g_b Color GetPixel(int x, int y) - pixel olvas void SetPixel(int x,int y,color Color) - pixel ír void Save(String ^, ImageFormat ) - Bmp, Emf, Exif, Gif, Guid, Icon, Jpeg, MemoryBmp, 3 Png, Tiff, Wmf
private: System::Void beolvasástoolstripmenuitem_click( System::Object^ sender, System::EventArgs^ e) { try {// Az image. image = gcnew Bitmap( "C:\\Users\\Public\\Pictures\\Sample Pictures\\Desert.jpg", true); // Set the PictureBox to display the image. Szín korrekció picturebox->image = image; // A pixel format this->text = String::Format("Pixel format: {", image->pixelformat); pirostoolstripmenuitem->enabled = true; catch (ArgumentException^) { MessageBox::Show("Hiba.", "Ellenőrizd a file-t!"); 4
...4 Bitképek módosítása a GetPixel() és SetPixel() lassú 5 private: System::Void pirostoolstripmenuitem_click(system::object^ sender, System::EventArgs^ e) { try { // Retrieve the image. image = gcnew Bitmap( "C:\\Users\\Public\\Pictures\\Sample Pictures\\Desert.jpg", true); int x, y; // Loop through the images pixels to reset color. for (x = ; x < image->width; x++) { for (y = ; y < image->height; y++) { Color pixelcolor = image->getpixel(x, y); Color newcolor = Color::FromArgb(pixelColor.R,, ); image->setpixel(x, y, newcolor); // Set the PictureBox to display the image. picturebox->image = image; // Display the pixel format in Label. this->text = String::Format("Pixel format: {", image->pixelformat); catch (ArgumentException^) { MessageBox::Show("Hiba.", "Ellenőrizd a file-t!"); /
...5 Bitképek gyors módosítása Bitkép rögzítése, adatainak kinyerése A bitkép bitjeinek áttöltése a nem menedzselt memóriába Módosítás, Visszatöltés nem menedzselt memóriából menedzselt memóriába A bitkép rögzítésének megszüntetése...5. A bitkép adatainak rögzítése BitmapData^ LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format[, BitmapData^ bitmapdata]); rect - a bitkép rögzíteni kívánt része ImageLockMode - felsorolás ReadOnly, WriteOnly, ReadWrite, UserInputBuffer format - volt (Gdi,Alpha,Format8bppIndexed ) bitmapdata - adatok a BitmapData^ osztályba töltve BitmapData osztály Tulajdonságok: Height, Width, Stride Scan - a scanline szélessége, a - az első pixel címe. System::Drawing::Imaging::BitmapData^ bmpdata = image->lockbits(rect, System::Drawing::Imaging::ImageLockMode::ReadWrite, image->pixelformat); 6
...5. A bitkép bitjeinek áttöltése a menedzselt és nem menedzselt memóriák közt System::Runtime::InteropServices::Marshal::Copy(ptr,Values,start,db); Nem menedzselt memóriából (ptr) a menedzselt memóriatömbbe (Values) start indextől db byte. IntPtr ptr = bmpdata->scan; int bytes = Math::Abs(bmpData->Stride) * image->height; // Memóriatömb a Bitmapnek array<byte>^values = gcnew array<byte>(bytes); // Átmásolás a memóriatömbbe System::Runtime::InteropServices::Marshal::Copy(ptr, Values,, bytes);...5.3 Módosítás a menedzselt memóriatömbben (Values)...5.4 Visszatöltés a menedzselt memóriából a nem menedzselt memóriába System::Runtime::InteropServices::Marshal::Copy(Values, start, ptr, db); A memória tömbből (Values) start indextől a memóriába(ptr) db byte. System::Runtime::InteropServices::Marshal::Copy(Values,, ptr, bytes);...5.5 A bitkép rögzítésének megszüntetése void UnlockBits(BitmapData^ bitmapdata); 7
8 private: System::Void gyorstoolstripmenuitem_click(system::object^ sender, System::EventArgs^ e) { Graphics ^ g = this->creategraphics(); g->drawimage(image, Point(, )); Rectangle rect = Rectangle(,, image->width, image->height); // Rögzítés System::Drawing::Imaging::BitmapData^ bmpdata = image->lockbits( rect, System::Drawing::Imaging::ImageLockMode::ReadWrite, image->pixelformat); IntPtr ptr = bmpdata->scan; int bytes = Math::Abs(bmpData->Stride) * image->height; // Memóriatömb a Bitmapnek array<byte>^values = gcnew array<byte>(bytes); // Átmásolás a memóriatömbbe System::Runtime::InteropServices::Marshal::Copy(ptr, Values,, bytes); // Módosítás for (int counter = ; counter<values->length; counter++) { if (counter % 3!=) Values[counter] = ; // Visszamásolás a memóriatömbből System::Runtime::InteropServices::Marshal::Copy(Values,, ptr, bytes); // Felszabadítás image->unlockbits(bmpdata); g->drawimage(image, image->width, ); picturebox->image = image;
. Open CV Computer Vision library (Open Source Computer Vision Library) Gépi látást segítő, nyílt forráskódú függvénykönyvtár. BSD (Berkley Software Distribution) licencelt. Több, mint 5 optimalizált algoritmus képek adatainak feldolgozására, objektumok felismerésére azonosítására képeken, arc felismerésre, pirosszem eltávolításra, képek összekapcsolására a felbontás növelése céljából, 3D modellezésre, sztereo 3D látás segítésére, objektumok és a kamera mozgásának követésére, emberi gesztusok felismerésére videofelvételeken, kiterjesztett valóság modellezésére, Gépi tanulás támogatására. C++, C, Python, Java és MATLAB interfészek Windows, Linux, Android és Mac OS környezetben. MMX (multimédiás utasításkészlet), SSE (Intel továbbfejlesztés), CUDA és OpenCL grafikus 9 kártya.
.. Az OpenCV telepítése https://opencv.org/ Pre-built libraries Libraries from source files... Az OpenCV a Visual Studio-ban View / Property Manager vagy Project / Properties A fordítónak az include állományok Függvények és struktúrák a linkernek Debug DLL - System Release
.. Az OpenCV ablakozása void namedwindow(const string& winname, int flags=window_autosize ) WINDOW_NORMAL - átméretezhető WINDOW_AUTOSIZE - képhez igazít WINDOW_OPENGL - OpenGL támogatás. void destroywindow(const string& winname) #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { namedwindow("picture",window_normal); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; destroywindow("picture"); return ;
..3 OpenCV Mat http://docs.opencv.org/trunk/d6/d6d/tutorial_mat_the_basic_image_container.html n dimenziós, többcsatornás (elemenként pl. pixelenként tárolt adatok száma) M i, i, i n i k < size[k] M egy lineáris n dimenziós tömb step[] azon bájtok száma, amelyet egy elem ugrás takar size[] a dimenziók határai addr M i, i, i n = addr M + +M. step i +M. step i + + +M. step n i n Pl: A3x3x3 byte tömb akkor step[] = 9, step[]=3, step[]= size[] = size[] = size[]=3
..3. Az OpenCV Mat osztály class CV_EXPORTS Mat { public:... int dims; // dim >= int rows, cols; // (-, -) ha dimenziós uchar* data; // az adatok pointere int* refcount; // a referencia számláló;... //... Metódusok ;..3.. Konstruktorok Mat::Mat() - üres Mat::Mat(Size size, int type) - size méretű type tömb Mat::Mat(int sor, int oszl, int type) - sor*oszl- méretű D-s type tömb type - CV_<bitek száma>{u S FC{<csatornák> pl: uchar ~ CV_8UC 3-elemű float pontkoord ~ CV_3FC3 3
..3.. Kifejezések (metódusok) A+B, A-B, -A, A*B A+s, A-s, s+a, s-a, A*alpha elemenkénti műveletek A.mul(B), A/B, alpha/a Transzponált A.t() Bitenkénti logikai operátorok A logicop B, A logicop s, s logicop A, ~A, ahol logicop : &,, ^ Matrix inverz különböző módszerekkel A.inv([módszer]) módszer : DECOMP_LU, DECOMP_CHOLESKY, DECOMP_SVD Elemenkénti minimum és maximum: min(a, B), min(a, alpha), max(a, B), max(a, alpha) Elemenkénti elérés: Az at<template>(koordináták) metódus a specifikált elemmel tér vissza template<typename _Tp > _Tp& cv::mat::at(int i = ) _Tp& cv::mat::at(int i, int i) _Tp& cv::mat::at(int i,int i,int i) Pl: Mat H(,,CV64F); for(int i = ; i < H.rows; i++) for(int j = ; j < H.cols; j++) H.at<double>(i,j)=./(i+j+);..3..3 Egyéb metódusok void Mat::create(int sor, int oszlop, int type) void Mat::create(int ndims, const int* sizes, int type) Mat& Mat::operator=(const Mat& m) void Mat::copyTo(OutputArray m) int Mat::type() const 4
..4 Képek beolvasása, megjelenítése, kiírása Mat imread(const string& filename, int flags= ) flags CV_LOAD_IMAGE_ANYDEPTH Ha az inputnak adott a mélysége, egyébként 8-bit (<). CV_LOAD_IMAGE_COLOR Színes (>) CV_LOAD_IMAGE_GRAYSCALE Szürke árnyalat (=) void imshow(const string& winname, InputArray mat) Létrehozza az ablakot, ha nem létezik és megmutatja a paramétertömböt bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>()) params típusfüggő tömörítési, minőségi előírások #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); imwrite("sivatag.jpg", kepbe); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; destroywindow("kep"); return ; 5
..5 Video beolvasása a VideoCapture osztály..5. Konstruktorok VideoCapture() VideoCapture(const string& filename) VideoCapture(int device)..5. Metódusok bool open( int device) bool open( const string &filename) bool isopened() VideoCapture & operator >> (Mat & image) void release()..5.. Kamera olvasása #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { VideoCapture cap; cap.open(); // default kamera az első if (!cap.isopened()) { cerr << "Nem olvasható a video" << endl; return -; namedwindow("picture", WINDOW_NORMAL); Mat frame; for (;;) { cap >> frame; if (frame.empty()) continue; imshow("picture", frame); int c = waitkey(3); if (c == 'q' c == 'Q') break; cap.release(); v destroywindow("picture"); return ; v 6
..5.. Video file olvasása #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { namedwindow("picture", WINDOW_NORMAL); VideoCapture v cap; // AVI video cap.open("c:\\users\\public\\videos\\samplevideos\\wildlife.wmv"); if (!cap.isopened()) { v cerr << "Nem olvasható a video" << endl; return -; Mat frame; for (;;) { try{ cap >> frame; imshow("picture", frame); //megmutatja a framet catch (...) { break; int c = waitkey(3); if (c == 'q' c == 'Q') break; cap.release(); destroywindow("picture"); return ; v v 7
..6 Video file írása a VideoWriter osztály..6. Konstruktorok VideoWriter() VideoWriter(const string& filename, int fourcc, double fps, Size framesize, bool iscolor=true) CV_FOURCC('M', 'J', 'P', 'G') codec kód generátor..6. Metódusok bool open(const string& filename, int fourcc, double fps, Size framesize, bool iscolor=true) bool isopened() VideoWriter& VideoWriter::operator<<(const Mat& image)..6.3 Felvevő #include "stdafx.h" #include <opencv/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main(int, char**) { namedwindow("picture", WINDOW_NORMAL); Mat src; VideoCapture cap(); // a default kamera a forrás if (!cap.isopened()) { cerr << "Nem olvasható a video\n"; return -; cap >> src; if (src.empty()) { cerr << "Nem sikerült a felvétel\n"; return -; 8
bool iscolor = (src.type() == CV_8UC3); VideoWriter v writer;//videowriter int codec = CV_FOURCC('M', v'j', 'P', 'G'); // 4 karakteres codec kód MJPG double fps = 5.; // a framerate string filename = "./live.avi"; writer.open(filename, codec, v fps, src.size(), iscolor); if (!writer.isopened()) v { // ha nem sikerült cerr << "Nem lehet kiírni\n"; return -; cout << "A videofile " << filename << endl; for (;;) //--- A GRAB és kiírás { try { cap >> src; catch (...){ break; v writer << src; imshow("picture", src); int c = waitkey(3); if (c == 'q' c == 'Q') break; // Dokumentumok mappa a Powerpointból destroywindow("picture"); // a videofile automatkusan zár a VideoWriter destructorral return ; 9
..7 A képtípus konvertálása void cvtcolor(inputarray src, OutputArray dst, int code, int dstcn= ) src input: 8-bit unsigned/ 6-bit unsigned ( CV_6UC... )/ single floating-point. dst output ugyanolyan méretű mint src. code konverzió CV_BGRGRAY, CV_RGBGRAY, CV_GRAYBGR, CV_GRAYRGB, CV_BGRHLS, CV_RGBHLS, CV_HLSBGR, CV_HLSRGB, CV_BGRHSV, CV_RGBHSV, CV_HSVBGR, CV_HSVRGB dstcn a csatornák száma, ha, akkor az input definiál #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { VideoCapture cap; cap.open(); // default kamera az első if (!cap.isopened()) { std::cerr << "Nem olvasható a video" << std::endl; return -; Mat frame, gray; for (;;) { cap >> frame; if (frame.empty()) continue; cvtcolor(frame, gray, COLOR_BGRGRAY); return ; v imshow("picture", frame); imshow("gray", gray); int c = waitkey(3); if (c == 'q' c == 'Q') break; 3
..8 Színfényesség-hisztogramm Windows Dockable Dialogs Histogram / Ablakok Dokkolható párbeszédablakok Hisztogramm Colors Information Histogram / Színek Információ Hisztogramm..8. Színsíkok szétvágása void split(const Mat& src, Mat* mvbegin) A többcsatornás tömböket csatornánlkénti tömbökre vágja src - a forrás matrix mv - a síkok tömbje vector<mat> bgr_planes; // a három színsík ( B, G and R ) split(src, bgr_planes); v..8. A hisztogramm(ok) számítása void calchist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histsize, const float** ranges, bool uniform=true, bool accumulate=false ) db% L images - A képek (azonos méretű és mélységű MAT-ok, ha több); nimages - A képek száma; channels - A csatornák listája (-images[i].chanels); mask - Opcionális maszk. Ha nem üres MAT, akkor ua. méret, csak a nem elemek számítanak, hist - Az output hisztogramok; dims - Az outputok darabszáma; histsize - A hisztogram(ok) vizsz. mérete; ranges - A hisztogram(ok) függ felbontása; uniform - Minden számított hisztogram azonos range méretű-e; accumulate- Egyszerre több összegzése. 3
..8.3 A tömbök - hisztogramm(ok) normalizálása void normalize(inputarray src, OutputArray dst, double alpha=, double beta=, int norm_type=norm_l, int dtype=-, InputArray mask=noarray() ) src Az input tömb; dst Az output tömb (azonos méretű). alpha A max érték amire normalizál, vagy az alsó határ (normtype=norm_minmax esetén); beta A felső határ (normtype=norm_minmax esetén); normtype A norma típusa (NORM_INF maximum n. NORM_L abs osszeg, NORM_L Euclidesi n), vagy NORM_MINMAX. dtype Ha negatív, akkor az src és a dst azonos típusú, egyébként azonos számú csatorna és CV_MAT_DEPTH mélység; mask optional operation mask. #include "stdafx.h" #include "opencv/highgui/highgui.hpp" #include "opencv/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> using namespace std; using namespace cv; int main(int argc, char** argv) { Mat src, gray, dst; src = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("sivatag", src); vector<mat> bgr_planes; // a három színsík ( B, G and R ) split(src, bgr_planes); v cvtcolor(src, gray, COLOR_BGRGRAY);// a szürkeárnyalat 3
int histsize = 8; float range[] = {, 56 ; const float* histrange = { range ; // A histogram mérete // A szintek // A szintek tömb Mat gray_hist, b_hist, g_hist, r_hist; /// hisztogram számítás: sík, db, csatorna, maszk, out, outdim, vizszmeret, függ meret calchist(&gray,,, Mat(), gray_hist,, &histsize, &histrange); calchist(&bgr_planes[],,, Mat(), b_hist,, &histsize, &histrange); calchist(&bgr_planes[],,, Mat(), v g_hist,, &histsize, &histrange); calchist(&bgr_planes[],,, Mat(), r_hist,, &histsize, &histrange); // Kirajzolás előkészítés int hist_w = 5; int hist_h = 4; int bin_w = cvround((double)hist_w / histsize); Mat histimage(hist_h, hist_w, CV_8UC3, Scalar(,, )); // Normalizál: in, out, alsoh, felsoh, mód, uatip, nincs maszk normalize(gray_hist, gray_hist,, histimage.rows, NORM_MINMAX, -, Mat()); normalize(b_hist, b_hist,, histimage.rows, NORM_MINMAX, -, Mat()); normalize(g_hist, g_hist,, histimage.rows, v NORM_MINMAX, -, Mat()); normalize(r_hist, r_hist,, histimage.rows, NORM_MINMAX, -, Mat()); // Kirajzolás for (int i = ; i < histsize; i++) { // Vonal : img, tól, ig, szín, vastagság, vonaltípus, eltolás line(histimage, Point(bin_w*(i - ), hist_h - cvround(gray_hist.at<float>(i - ))),Point(bin_w*(i), hist_h - cvround(gray_hist.at<float>(i))), Scalar(7, v 7, 7),, 8, ); line(histimage, Point(bin_w*(i - ), hist_h - cvround(b_hist.at<float>(i - ))), Point(bin_w*(i), hist_h - cvround(b_hist.at<float>(i))), Scalar(55, v, ),, 8, ); line(histimage, Point(bin_w*(i - ), hist_h - cvround(g_hist.at<float>(i - ))), Point(bin_w*(i), hist_h - cvround(g_hist.at<float>(i))), Scalar(, v 55, ),, 8, ); line(histimage, Point(bin_w*(i - ), hist_h - cvround(r_hist.at<float>(i - ))), Point(bin_w*(i), imshow("calchist", histimage); waitkey(); return ; hist_h - cvround(r_hist.at<float>(i))), Scalar(,, 55),, 8, ); v 33
..9 Képhibák javítása..9. Konvolúció A képpont és környezete világosságának súlyozott összege R q ( k, l) t g( k, l) t( r, s) g( k r, l s) S rrss g - a képpont eredeti világossága q - a képpont új világossága t - a súlyok (az operator), rendszerint páratlan számú sort és oszlopot tartalmaz void filterd(inputarray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=point(-,-), double delta=, int bordertype=border_default ) src Az input; dst Az output azonos méret és azonos csatorna; ddepth A kívánt output adatmélység (hány bites). Ha -, akkor az input a meghatározó; kernel A konvolúciós mátrix. anchor A célpont helye a konvolúciós mátrixban. A (-,-) a középpont; delta Opcionális hozzáadott érték a pixelekhez; bordertype Extrapoláció a határon, extrapoláció a default. Szűrők Általános Konvolúciós mátrix / Filters Generics Convolution Matrix 34
#include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat kern = Mat::zeros(3, 3, CV_8S); kern.at<char>(, ) = -; kern.at<char>(, ) = -; kern.at<char>(, ) = -; kern.at<char>(, ) = -; kern.at<char>(, ) = 5; Mat kepki; // Konvolúció: in, out, inmélysége, konvmatrix filterd(kepbe, vkepki, -, kern); imshow("fdkep", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 35
..9. Elmosás/Blur A képpont és környezete világosságának átlaga - lágyít Filters Blur Blur / Szűrők Elmosás Elmosás K = ksize. width ksize. height void blur(inputarray src,outputarray dst,size ksize,point anchor=point(-,-),int bordertype=border_default) src Az input (bárhány csatorna); dst Az output ugyanakkora, mint az src; ksize A kernel mérete; anchor A kernel kezdőpontja, a default (-,-) a középpont; bordertype A képen kívül az extrapoláció a default. #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat kepki; blur(kepbe, kepki, v Size(9,9)); imshow("blur", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 36
..9.3 Gauss-elmosás / Gaussian Blur Filters Blur Gaussian Blur / Szűrők Elmosás Gauss-elmosás Minden (vagy a kiválasztott) pixel(ek) helyére beállítható méretű környezet súlyozott átlaga kerül lágyít Többször használható - Ctrl F IIR - infinite impulse response nem számítógépes ábrák, nagy környezet. RLE - run-length encoding. Számítógépes ábra nagy egyszínű részekkel.
A normális eloszlás haranggörbéje Két dimenzióban a magfüggvény x σ σ π e G x, y = Ke x σ y σ σ a szórás, a várható érték void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmax, double sigmay=, int bordertype=border_default ) src Az input (bárhány csatorna); dst Az output ugyanakkora, mint az src. ksize A méret; sigmax Az x irányú szórás; sigmay Az y irányú szórás (ha, akkor ua, mint sigmax); bordertype A képen kívül az extrapoláció. #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat kepki; GaussianBlur(kepbe, vkepki, Size(9, 9),3); imshow("gaussblur", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 38
..9.4 Medián szűrés Egypontos hibákra jó, nem lineáris. void medianblur(inputarray src, OutputArray dst, int ksize) src Az input -, 3-, or 4 csatorna; dst Az output ugyanaz a méret mnt az src; ksize A méret>, páratlan. #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat kepki; medianblur(kepbe, v kepki, 9); imshow("medianblur", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 39
- - - - 5 - - - - Blur GaussBlur MedianBlur 4
4.. Élkeresés... A változás sebességének vizsgálata (Gradiens) Vízszintes és függőleges irányú változásokat parciális differencia képzésével emelhetjük ki. ), ( ), ( ), ( l k g l k g x g l k d ), ( ), ( ), ( l k g l k g y g l k d, r r arctg r r Gr Élkeresés differencia kereséssel (Differencial) r r Filters Edge Detection Edge Differential / Szűrők Élkeresés Szélek Differenciál, r r arctg r r Gr Gaussok különbsége / Different of Gaussian DoG Filters Edge Detection Different of Gaussian / Szűrők Élkeresés Gaussok különbsége
4 Roberts módszere A változás sebessége a jobbra lefelé és a balra lefelé szomszéd vizsgálatával. Az átlós, vékonyabb vonalakat keresi., r r 4, r r arctg r r Gr Filters Edge Detection Edge Roberts / Szűrők Élkeresés Szélek Roberts Prewit módszere A változás sebessége a vízszintes és a függőleges irányban A vízszintes és a függőleges vonalakat keresi. 6, 6 p p P P arctg, P P Gr Filters Edge Detection Edge Prewit compass/ Szűrők Élkeresés Szélek Prewit iránytű
43... Sobel módszere A változás sebessége a vízszintes és a függőleges irányban áltagoló differenciál operátorral. 8, 8 s s, s s arctg s s Gr Filters Edge Detection Edge Sobel/ Szűrők Élkeresés Szélek Sobel Filters Edge Detection Sobel/ Szűrők Élkeresés Sobel
A Sobel függvény magasabbrendű deriváltakra is kiterjeszti a számítást. void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=, double delta=, int bordertype=border_default ) src Az input; dst Az output ugyanolyan méret és csatornaszám mint az src; ddepth Az output mélysége (hány bites), - esetén ua, mint az src; dx hanyadik derivált x irányban; dy hanyadik derivált y irányban; ksize a kiterjesztett Sobel kernel mérete, 3, 5, vagy 7; scale opcionális derivált nagyítási faktor; delta az eredmények opcionális eltolása. bordertype A határ extrapolációja (default extrapoláció). #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat gray; cvtcolor(kepbe, gray, v CV_BGRGRAY); imshow("szurke", gray); Mat kepki; return ; v Sobel(gray, kepki, CV_8U,, ); imshow("sobel", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; 44
... Élkeresés a változás gyorsulása alapján (Laplace) 8, 4,, ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( l k g l k g l k g l k g l k g l k g l k g l k d l k d d l k dd x x 45 ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( ), ( l k g l k g l k g l k g l k g l k g l k g l k d l k d d l k dd y y Vízszintes Függőleges Vízszintes + függőleges Vízszintes+függőleges+átlós void Laplacian(InputArray src, OutputArray dst, int ddepth, int ksize=, double scale=, double delta=, int bordertype=border_default ) src Az input; dst Az output ugyanolyan méret és csatornaszám mint az src; ddepth Az output mélysége (hány bites), - esetén ua, mint az src; ksize a kiterjesztett Sobel kernel mérete páratlan, pozitív; scale opcionális derivált nagyítási faktor; delta az eredmények opcionális eltolása. bordertype A határ extrapolációja (def:extarpoláció). Filters Edge Detection Edge Laplace/ Szűrők Élkeresés Szélek Laplace
#include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat gray; cvtcolor(kepbe, gray, v CV_BGRGRAY); imshow("szurke", gray); Mat kepki; // In, out, melység Laplacian(gray, kepki, v CV_8U); imshow("sobel", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 46
...3 Élkeresés a Canny módszerével. Gauss zajszűrés. Vízszintes és függőleges gradiens komponensek Az irány kerekítve,45,9,35 fokra 3. Nem maximum eltüntetés (csak akkor és, ha kiemelkedő) 4. Gradiens küszöb G > küszöb felső él jelölt G < küszöb alsó nem éljelölt Ha G > küszöb alsó és G < küszöb felső éljelölt ha a szomszédos G > küszöb felső : vagy 3: a javasolt küszöb felső :küszöb alsó arány void Canny(InputArray image, OutputArray edges, double threshold, double threshold, int aperturesize=3, bool Lgradient=false ) image edges threshold threshold aperturesize Lgradient egy csatornás 8-bit input. output él térkép azonos méretben. alsó határ. felső határ. a Sobel() operátor mérete. pontosabb, vagy kevésbé pontos gradiens norma. 47
#include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat gray; cvtcolor(kepbe, gray, v CV_BGRGRAY); imshow("szurke", gray); Mat edge; // In, out, tralsó, trfelső Canny(gray, edge, v 64,8); imshow("canny", edge); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 48
Sobel Laplace Canny 49
.. Képek élesítése... Csúszka int createtrackbar(const string& trackbarname, const string& winname, int* value, int max, TrackbarCallbackonChange= on_trackbar, void* userdata=) void on_trackbar(int, void*) { k S Id k L 4 k 4k k Élesítő tényező (/4, /8, /6) k... Élesítő konvolúció (filterd) #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int slider = ; int slidermax = ; void on_trackbar(int, void*) { // csuszka esemeny int main(int argc, char** argv) { VideoCapture cap; cap.open(); // default kamera az első namedwindow("eleskonv", WINDOW_NORMAL); createtrackbar("eles","eleskonv", &slider, v slidermax, on_trackbar); //Csuszka Mat frame; Mat kepki; for (;;) { return ; v cap >> frame; if (frame.empty()) continue; imshow("picture", frame); Mat kern = Mat::zeros(3, 3, CV_8S); kern.at<char>(, ) = -slider; kern.at<char>(, ) = -slider; kern.at<char>(, ) = -slider; kern.at<char>(, v ) = -slider; kern.at<char>(, ) = +4*slider; filterd(frame, kepki, -, kern); // in, out, in a meghatározómélys, a mag imshow("eleskonv", kepki); int c = waitkey(3); if (c == 'q' c == 'Q') break; 5
...3 Éles kép=.5*kép-.5*blur(kép) void addweighted(inputarray src, double alpha, InputArray src, double beta, double gamma OutputArray dst, int dtype=-); src az első input tömb. alpha az első input tömb súlya. src a második input tömb. beta a második input tömb súlya. gamma skalár minden szummához hozzáadva. dst az output tömb. dtype A kívánt output adatmélység (hány bites). Ha -, akkor az input a meghatározó; dst = saturate(src alpha + src beta + gamma) saturate = min(max x,, max x ) #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat image; //in, out, méret, xszórás GaussianBlur(kepbe, image, vcv::size(3, 3), 3); Mat kepki; addweighted(kepbe,.5, image, v -.5,, kepki); imshow("eles", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 5
...4 Élességállítás z elteres(z) = szelesség magassag szelesseg magassag i= j= frame i, j blur(frame i, j = max 5
53...5 Zajcsökkentő élkiemelés Növelt területű Prewitt operátor, #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat kepbe = imread("c:\\users\\public\\pictures\\sample Pictures\\Desert.jpg"); imshow("kep", kepbe); Mat image; Mat kern = Mat(Size(7, 7), CV_8S); kern = Mat::zeros(7, 7, CV_8S); for (int i = ; i < 7; i++) for (int j = ; j < 7; j++) { if (j < 3) kern.at<char>(i, j) = -; if (j > 3) kern.at<char>(i, j) = ; filterd(kepbe, image, -, kern); //in, out, az input mélység az alap, a mag Mat kepki; kern = Mat::zeros(7, 7, CV_8S); for (int i = ; i < 7; i++) for (int j = ; j < 7; j++) { if (i < 3) kern.at<char>(i, j) = -; if (i > 3) kern.at<char>(i, j) = ; filterd(image, kepki,, kern); imshow("maxprew", kepki); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; v v v v
54 -k -k -k -k +4*k -k -k -k -k.5*kép-.5*blur(kép),
...6 Intenzitás korrekció Intenzitástartomány kiemelése intenzitás float eh[4] = { 4.6977377596e-5, -.567446595573, 4.97747475967, -89.6437649854 ; uchar gamma(uchar xbe){ double x = double(xbe); if (x < ) return ; else return eh[]*x*x*x + eh[]*x*x + eh[]*x +eh[3]; VideoCapture cap; // AVI video cap.open("c:\\munka\\83_teszt_8-9-4---56_free_.avi"); Mat frame, gframe; for (;;) { try { cap >> frame; gframe = frame.clone(); imshow("picture", frame); //megmutatja a framet for (int i = ; i < frame.cols*3; i++) for (int j = ; j < frame.rows; j++) gframe.at<uchar>(j, i) = gamma(frame.at<uchar>(j, i)); imshow("gamma", gframe); //megmutatja a framet catch (...) { break; int c = waitkey(3); if (c == 'q' c == 'Q') break; f()= f'()=4 f(55)= f'(55)= intenzitás z=; m=4; A=[x^3,x^,x,;3*x^,*x,,;3*55^,*55,,;55^3,55^,55,]; B=[,m,,z]'; xx=linsolve(a,b) figure ('Name', 'Interpoláció',... % grafikus ablak 'NumberTitle','off'); z=::55; plot(z,z,'-b',z,f(z,xx),'-r'); % függvényrajzolás shg; function y=f(x,xx) % függvény-definíció y=xx(4)+xx(3)*x+xx()*x.^+xx()*x.^3; end 55
.. Szegmentálás Szegmentálás, csoportosítás, rendezés érzékelés alapján (Segmentation, grouping, perceptual organization): az összetartozó jellemzők összegyűjtése, csoportosítása Szegmentálás felülről lefelé (Top-down ): közös ismert objektum hasonló pixeleinek keresése Szegmentálás lentről fölfelé (Bottom-up ): azonos jellegű pixelek összegyűjtése pixelből indítva... Globális szegmentálás küszöbértékekkel ( ) Ha a hasonló intenzitású keresett elem és a háttér között nagy a kontraszt. k(x,y)<=t (objektum) db% k(x,y)>t (háttér) T vagy k(x,y)>=t (objektum) k(x,y)<t (háttér) bináris képet készít. L intenzitás 56
threshold(inputarray src, OutputArray dst, double thresh, double maxval, int type) src Az input tömb ( csatorna, 8-bit vagy 3-bit floating point); dst Az output tömb azonos méret; thresh A threshold érték; maxval A használt max érték (THRESH_BINARY és THRESH_BINARY_INV esetén); type THRESH_BINARY, THRESH_BINARY_INV, TRESH_TRUNC, TRESH_TOZERO, TRESH_TOZERO_INV. #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int slider = ; int slidermax = ; void on_trackbar(int, void*) { // csuszka esemeny int main(int argc, char** argv) { VideoCapture cap;cap.open(); // default kamera az első namedwindow("picture", WINDOW_NORMAL); namedwindow("szurke", WINDOW_NORMAL); namedwindow("treshold", WINDOW_NORMAL); int slider = 7; int slidermax = 55; createtrackbar("csuszka", "Treshold", &slider, slidermax, on_trackbar); //Csuszka Mat frame, gray, trash; for (;;) { cap >> frame; if (frame.empty()) continue; imshow("picture", frame); cvtcolor(frame, gray, CV_BGRGRAY); imshow("szurke", gray); threshold(gray, trash, slider, 55, TRESH_BINARY); return ; v imshow("treshold", trash); int c = waitkey(3); if (c == 'q' c == 'Q') break; 57
... Az Isodata algoritmus ( ) I. A hisztogram két részre (T ) II. A két jellemző terület intenzitás közepe m (T ) = L i <T p il i L i <T p i M (T ) = L i T p i L i L i T p i III. Az új közép T =(M +m )/ m j+ (T j ) = IV. Ameddig T j+ - T j <ε L i <T j p il i L i <T j p i M j+ (T j ) = Li Tj p i L i L i T j p i p T - db% m m T T M M L intenzitás 58
... Otsu módszere ( ) Keresi azt a T küszöbértéket, melyre minimális a két rész szórásnégyzeteinek súlyozott átlaga (σ ) σ (T) = ω T σ +ω T σ Darabszámok a hisztogram két felén ω (T) = Li <T p i ω (T) = Li T p i A p i hisztogram elemekkel kifejezve a várható érték T μ (T) = L i <T p il i ω (T) μ (T) = L i T p il i ω (T) p (db) µ µ A szórásnégyzet a két félen σ T = L i <T p i μ (T) ω (T) σ T = Bizonyítható, hogy σ (T) = ω T σ +ω T σ L i T p i μ (T) ω (T) minimális ha L intenzitás Γ (T) = ω T ω T μ T μ T maximális 59
... Adaptív (lokális) szegmentálás küszöbértékekkel ( ) void adaptivethreshold(inputarray src, OutputArray dst, double maxvalue, src dst maxval adaptivemethod hresholdtype blocksize C #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { VideoCapture cap; cap.open(); // default kamera az első Mat frame, gray, trash; for (;;) { cap >> frame; if (frame.empty()) continue; imshow("picture", frame); cvtcolor(frame, gray, CV_BGRGRAY); imshow("szurke", gray); return ; int adaptivemethod, int thresholdtype, int blocksize, double C) A forrás 8-bites tömb. Az output tömb azonos méret; A használt max érték (THRESH_BINARY és THRESH_BINARY_INV esetén); Az algoritmus ADAPTIVE_THRESH_MEAN_C esetén a környezet átlaga vág; ADAPTIVE_THRESH_GAUSSIAN_C esetén a környezet Gauss maggal súlyozott átlaga vág; Hogyan vág THRESH_BINARY, THRESH_BINARY_INV; A figyelembe vett négyzet oldala 3,5,7, ; Levonódik az átlagból. adaptivethreshold(gray, trash, 55, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,9,); imshow("treshold", trash); int c = waitkey(3); if (c == 'q' c == 'Q') break; v 6
... Küszöbérték lokális hisztogram alapján ( ) Niblack algoritmus Vágás a lokális várható érték (m) és a standard szórásnégyzet (s) alapján. T Nb = m + k s k =. Sauvola algoritmus T Nb = m + k N p N P p i m p i a pontok "színe i= N p a pontok száma T S = m + k s max(p i ) k =.5 Wolf módszer T W = k m + k min p i + k s max p i m min p i k =.5 6
AdaptiveTreshold Treshold 6
...3 Részhalmazokra bontás fuzzy logikával ( ). A hibás pontok kiszűrése. A pontok fényessége közti különbségek minimális, átlagos és maximális értéke minimum, átlag és maximum. 3. A pontok fényessége közti különbség kicsi, közepes és nagy lehet. Annak valószínűségét, hogy a pontpár távolsága melyik csoportba tartozik, az ábra, szakaszonként lineárisan változó görbéi szerint alakul (fuzzyfüggvények) 4. Válasszuk ki a legfényesebb pontot! 3. Vizsgáljuk az összes többi pontot! Ha az éppen vizsgált pont és a legfényesebb pont fényességének különbsége legnagyobb valószínűséggel nagy, akkor a pont a nemfényes csoportba kerül 4. Egyébként a fényesek közé. valószínűség kicsi közepes nagy minimum átlag maximum pontpárok távolsága 63
...4 Elárasztás ( ) Tartománymagok kijelölése (pl. egy nem sorolt pont) Tartományok növelése a homogenitási feltétellel szín, homogenitás statisztika a tartományon int floodfill(inputoutputarray image, Point seedpoint, Scalar newval, Rect* rect=, Scalar lodiff=scalar(), Scalar updiff=scalar(), int flags=4 ) int floodfill(inputoutputarray image, InputOutputArray mask, Point seedpoint, Scalar newval, Rect* rect=, Scalar lodiff=scalar(), Scalar updiff=scalar(), int flags=4 ) image (mask) seedpoint newval rect lodiff updiff flags A kitöltés OpenCV osztály (pl- Mat) I/O. 3 csatornás, 8-bitites vagy float. Módosul az első ovrload-ban, a illetve a másodikban ha a flags FLOODFILL_MASK_ONLY beállított.. Opcionális, egycsatornás 8 bites image+ oszlop + sor. Inputként a nem pixelek leállítják a kitöltést, outputként a kitöltött pixelelek értéke ; A kezdőpont;. A kifestett pixelek értéke; Opcionális output parametert a függvény állítja a legkisebb kifestett tégla; A max. alsó fényesség/szín eltérés a vizsgált és a már kifestett,szomszédos pixelek, vagy kezdőpont közt; A max. felső fényesség/szín eltérés a vizsgált és a már kifestett szomszédos pixelek, vagy kezdőpont közt. Az első 8 bit a kapcsolódást beállító érték. A default a 4 esetén csak a legközelebbi szomszédok. 8 esetén a sarkok is. A következő 8 bit a kitöltő érték (default ). A többi bitszintű OR-ral ( ) ha a FLOODFILL_FIXED_RANGE beállított akkor a maggal, egyébként a szomszéddal hasonlít, ha a FLOODFILL_MASK_ONLY akkor a mask-kal beállított helyeken a -5 bitekkel fest. src x seed, y seed lodiff src x, y src x seed, y seed + updiff Képlet szerint fényesség vagy R,G,B síkok. 64
#include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { VideoCapture cap; cap.open(); // default kamera az első if (!cap.isopened()) { std::cerr << "Nem olvasható a video" <<std::endl; return -; Mat frame, gray; for (;;) { cap >> frame; if (frame.empty()) continue; cvtcolor(frame, gray, COLOR_BGRGRAY); imshow("picture", frame); // in, középpont, festőszín, mintégla, mindiff, maxdiff csak szomszéd return ; v floodfill(gray, Point(gray.cols /, gray.rows / ), 55, &Rect(,,5,5), Scalar(), Scalar()); imshow("gray", gray); int c = waitkey(3); if (c == 'q' c == 'Q') break; 65
...4. Elárasztás statisztikával ( ) Tartománymagok kijelölése (pl. egy nem sorolt pont) Tartományok növelése a statisztikával Legyen P a vizsgált pont intenzitása, körülötte T tartományban N szomszédos pont! A tartományban p i a pontok intenzitása μ = N T p i az intenzitás várható értéke σ = N T μ p i az intenzitás korrigált tapasztalati szórásnégyzete τ = N P μ N+ σ τ K küszöbszám akkor szomszédos pont a régióhoz tartozik. 66
...5 Szegmentálás tartományokkal ( ) A kép tartományai legyenek T i -k! A tartományok lefedik a teljes (T) képet A tartományoknak nincs közös pontjuk T i = T T i T j = ha i j Minden tartományra megfogalmazható homogenitási kritérium (H) Szomszédos tartományok uniója nem homogén H(T i ) = igaz H R i R j = hamis ha R i és R j szomsz. 67
...5. Vágás és egyesítés Legyen a homogenitási feltétel P(T) = igaz ha a T tartomány pontjai kevéssé eltérő színűek!. Vágjuk az inhomogén képet (P(T)=false) négy részre!. Ha a szomszédos területek homogének P(T i + T i+ )=igaz, akkor azokat vonjuk össze. 3. Az inhomogén területeket vágjuk újabb 4 részre! : : 3 68
...5. Csoportosítások...5.. Klaszterezés Legyen adott k darab diszjunkt tartomány (klaszter)! C, C, C k! A pontok intenzitása p i Jelölje μ, μ, μ k a C i tartományokban az intenzitás-középértékeket! A tartományokban számíthatjuk a intenzitások a a tartomány intenzitás átlagától számított négyzetes eltéréseinek összegét. k LSE = p i μ j j= p i C j Az összes csoportosítás közül az lesz a legjobb, ahol a tartományok fenti négyzetes eltéréseinek összege a legkisebb. (Least Square Error) LSE = min 69
...5.. K-means algoritmus. Kiválasztja a klaszterek számát (k).. A felhasználó önkényesen, vagy véletlenszerűen létrehoz k számú klaszterközéppontot. 3. Minden egyes pontot abba a klaszterbe sorol, amelynek középpontjához a legközelebb helyezkedik el (RGB, xyrgb térben). 4. Kiszámolja az új klaszter középpontokat. 5. Addig ismétli az előző két lépést (iterál), amíg valamilyen konvergencia kritérium nem teljesül (általában az, hogy a besorolás nem változik). Arthur and Vassilvitskii javaslata. Két klaszterben (Y, Z) legyen X az a pont amelyik intenzitását (RGB távolságát, xyrgb távolságát) tekintve leginkább eltér (D) saját klaszterének intenzitás átlagától!. Legyen q a klaszterek átlagintenzitásai (átlag RGB távolságai, átlag xyrgb távolságai) közti átlagos különbség! 3. Ha D>q/, akkor új klaszter keletkezett az aktuális X középponttal. 7
double kmeans(inputarray data, int K, InputOutputArray labels, TermCriteria criteria, int attempts, int flags, OutputArray centers=noarray() ) data K labels criteria attempts flags centers A csoportosítandó adatok n dimenziós float koordinátájú ponttömbben. Pl. count elemű RGB tömb: Mat points(count, 3, CV_3F); Mat points(count, CV_3FC3); std::vector<cv::point3f> points(count); A csoportok kívánt száma; I/O egésztömb, minden ponthoz tartozik majd egy klaszterindex; A leállási feltétel, az iterációk száma és/vagy a pontosság. struct TermCriteria{ int type,//cv_termcrit_iter és/vagy CV_TERMCRIT_EPS int maxcount, double epsilon ; A kísérletek száma; A működési mód: KMEANS_RANDOM_CENTERS - minden kísérletnél véletlen kezdőpontok. KMEANS_PP_CENTERS - speciális középpont választás Arthur and Vassilvitskii javaslata; KMEANS_USE_INITIAL_LABELS - a felhasználó által definiált középpontok; A klaszter középpontok egy klaszter-adatsor minden középponthoz. A visszatérési érték a adatpontok és a hozzájuk tartozó középpontok közti eltérések négyzetösszege. i p i center pi 7
#include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat src = imread("gyumolcs.jpg"); imshow("image", src); Mat samples(src.rows * src.cols, 3, CV_3F); for (int y = ; y < src.rows; y++) for (int x = ; x < src.cols; x++) for (int z = ; z < 3; z++) // áttölti vektorba samples.at<float>(y + x*src.rows, z) = src.at<vec3b>(y, x)[z]; int clustercount = 5; Mat labels; int attempts = 5; Mat centers; //BGRkép, klaszterdb, klindex, iter, kísérletek, spec javaslat,középpontokszínei kmeans(samples, clustercount, labels, TermCriteria(CV_TERMCRIT_ITER CV_TERMCRIT_EPS,,.), attempts, KMEANS_PP_CENTERS, centers); v Mat new_image(src.size(), src.type()); for (int y = ; y < src.rows; y++) for (int x = ; x < src.cols; x++) { int cluster_idx = labels.at<int>(y + x*src.rows, ); //a pont csoportja new_image.at<vec3b>(y, x)[] = centers.at<float>(cluster_idx, ); new_image.at<vec3b>(y, x)[] = centers.at<float>(cluster_idx, ); new_image.at<vec3b>(y, x)[] = centers.at<float>(cluster_idx, ); // csoportszínezés imshow("clustered image", new_image); for (;;) { char key = (char)waitkey(); if (key == 7 key == 'q' key == 'Q') break; return ; 7
..3 Alakfelismerés..3. Alakfelismerés sablonillesztéssel r n i n i ( sz ( sz i i sz sz ) ) ( sz n i i ( sz sz i ) sz A korrelációs (a várható értéktől való eltérések szorzata covariancia osztva a szórások szorzatával) együttható két tetszőleges elemhalmaz közötti lineáris kapcsolat nagyságát és irányát jellemzi A minta (sz ) korrelációja a kép részleteivel (sz ) A legjobb illeszkedést az a képrészlet adja, amelyre a korrelációs együttható a legnagyobb...3. D korreláció konvolúcióval Y M N m,n X S i j S( i, j ) X( m i,n j ) S a a keresendő minta, X a kép Y az a hely mennyire hasonlít a mintára célszerű elvégezni valamilyen élkiemelő szűrést ) 73
..3. Alakfelismerés Hough transzformációval..3.. Egyenesek Azon (x,y) síkbeli pontok, melyekre a normálegyenlet teljesül (Hesse-féle normálegyenlet) r = (x, y) (cosθ,sinθ) r Θ n(cosθ,sin Θ) (x,y) Egyetlen térbeli pont egy egyenes-sereggel modellezhető, melynek adatai az origóból húzott merőleges hossza (r) és ennek szöge Θ r Hough tér r r Θ A pontot jellemző egyenesek a képtérben A paramétertér sin(θ) jellegű görbéjének minden egyes pontjához a képtér egy pontot definiáló egyenese tartozik π π Az egyenesek paraméterei a paramétertérben Θ 74
y r x Ha a képtér minden egyes pontját transzformáljuk egymást metsző görbéket kapunk. Θ π π A görbék metszéspontja a képpontok egyeneséhez tartozik. Ennek origótól mért távolsága r és Θ szöge mérhető Keressük tehát a metszéspontokat (a Hough tér pixeleinek lokális maximuma) amelyek a képtér egyeneseit jelentik. 75
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=, double stn= ) image 8-bit, egycsatornás bináris kép. lines A vonalak vektora (r,θ) adatokkal jellemezve. rho Távolság érzékenység. theta Szög bontás (radián). threshold Hough köszöb. 76
#include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat vonalbe = imread("vonalak.bmp"); Mat vonalak; cvtcolor(vonalbe, vonalak, COLOR_BGRGRAY); vector<vecf> lines; //in, vonalak tömbje, távérz, szögbontás, threshold HoughLines(vonalak, lines, v, CV_PI / 6, ); Mat vonalak = Mat::zeros(vonalak.rows, vonalak.cols, CV_8UC); for (size_t i = ; i < lines.size(); i++) { float rho = lines[i][], theta = lines[i][]; Point pt, pt; double a = cos(theta), b = sin(theta); double x = a*rho, y = b*rho; pt.x = cvround(x + * (-b)); pt.y = cvround(y + * (a)); pt.x = cvround(x - * (-b)); pt.y = cvround(y - * (a)); line(vonalak, pt, vpt, 55, 3, CV_AA); // kép, kezdpt, vegpt, szín, vastagság, antialiasedvonal char ki[]; sprintf_s(ki, "%i", lines.size()); string s = ki; imshow("alap", vonalbe); imshow("hough" + s, vonalak); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 77
..3.. Körök Egy kör egyenlete D-ben (x a) + (y b) = r (a,b) a középpont és r a sugár. Két lépésben fix sugarú körök középpontját keressük, és aztán keressük az optimális sugarat. D-ben minden egyes körponthoz (bal ábra) a centrum az ismert sugarú körön van (jobb ábra). A körök metszéspontja lesz középpont. For each pixel(x,y) For each radius r = to r = 6 // a lehetséges sugarak For each theta t = to 36 // a lehetséges szögek -36 a = x r * cos(t * PI / 8); // a középpont a koord b = y r * sin(t * PI / 8); // a középpont b koord A[a,b,r] +=; // szavazás end end end Ha nem ismerjük a rádiuszt, akkor a 3D helyett iterálunk.. Létrehozunk egy akkumulátor mátrixot A[a,b,r]=,. GaussBlur után szürkeárnyalatos képet készítünk, 3. A lehetséges sugarakon végigmenve számláljuk a köröket. Minden pixelen keresünk rmin és rmax között t=-36 fokig polár koordinátás köröket és ha elég sok metszéspont van a körön, akkor A[a,b,r] +=. 4. A lokális maximumok a lehetséges körök a Hough síkon. 5. A maximum a keresett kör. 78
void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double mindist, double param=, double param=, int minradius=, int maxradius= ) image 8-bites, egycsatornás input; circles A körök output vektora (Vec3f); method A módszer csak CV_HOUGH_GRADIENT ; dp A kép és a kör-akkumulátor felbontásának inverz viszonya, dp= ugyanaz a felbontás. mindist Minimum távolság a körök között. param Parameter, CV_HOUGH_GRADIENT esetén Canny küszöb, a magasabb, az alacsonyabb a fele. param Parameter, CV_HOUGH_GRADIENT esetén a küszöb a középpontok keresésénél; minradius Minimum sugár; maxradius Maximum sugár. #include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat korbe = imread("korok.jpg"); Mat korgray; cvtcolor(korbe, korgray, COLOR_BGRGRAY); vector<vec3f> korok; HoughCircles(korgray, korok, CV_HOUGH_GRADIENT,, v korgray.rows /,,,, korgray.rows / ); for (size_t i = ; i < korok.size(); i++) { Point center(cvround(korok[i][]), cvround(korok[i][])); int radius = cvround(korok[i][]); circle(korbe, center, 3, Scalar(, v 55, ), -, 8, ); circle(korbe, center, radius, v Scalar(,, 55), 3, 8, ); // kép, közpt, sugár, szín, vonalvast, vonaltip, tizedesek száma char ki[]; sprintf_s(ki, "%i", korok.size()); string s = ki; imshow("alap" + s, korbe); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 79
..3.3 Előtér, háttér grabcut algoritmus A különböző színek előfordulási valószínűségét és szomszédos pixelek hasonlóságát leíró energiafüggvény optimálásán alapuló módszer void grabcut(inputarray img, InputOutputArray mask, Rect rect, InputOutputArray bgdmodel, InputOutputArray fgdmodel, int itercount, int mode=gc_eval ) img mask rect bgdmodel fgdmodel itercount mode Input 8 bites 3 csatornás kép; I/O 8 bites egycsatornás maszk. Ha a mode GC_INIT_WITH_RECT, akkor a függvény inicializál az alábbi elemekkel: GC_BGD - nyilvánvaló előtér pixel, GC_FGD - nyilvánvaló háttér pixel, GC_PR_BGD - lehetséges háttér pixel, GC_PR_FGD - lehetséges előtér pixel; A szegmentálandó objektumot befoglaló téglalap ha a mode= GC_INIT_WITH_RECT; Átmeneti előtér tömb. Átmeneti háttér tömb. Az iterációk száma. Újra indítható a mode=gc_init_with_mask vagy mode=gc_eval paraméterekkel;. a számítás módja: GC_INIT_WITH_RECT - téglalapban (rect) dolgozik a függvény,. GC_INIT_WITH_MASK - megadott maszkkal dolgozik a függvény a GC_INIT_WITH_RECT és GC_INIT_WITH_MASK kombinálható, ilyenkor a téglalapon kívülháttér van (GC_BGD). GC_EVAL - folytatni lehet egy megszakított számítást. void compare(inputarray src, InputArray src, OutputArray dst, int cmpop) Összehasonlít két tömböt, vagy egy tömböt és egy előteret/hátteret elemenként src Az első egycsatornás tömb; src A második egycsatornás tömb, vagy egy konstans ami egy szám (jelölhet jelleget GC_BGD, GC_FGD, GC_PR_BGD, GC_PR_FGD); dst Az output tömb; cmpop Az összehasonlítás jellege (CMP_EQ, CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_NE) 8
#include "stdafx.h" #include <opencv/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat image = cv::imread("lena.jpg"); Mat image = image.clone(); Rect rect(4, 4, image.cols -, image.rows - 7);// határoló rectangle Mat result; Mat bgmodel, fgmodel; //kép, eredm, rect, temp, temp, iterdb, initmód grabcut(image, result, rect, bgmodel, v fgmodel,, cv::gc_init_with_rect); compare(result, GC_PR_FGD, v result, CMP_EQ); //in, előteret keres, eredmény, = az előtérrel Mat foreground(image.size(), CV_8UC3, Scalar(,, )); image.copyto(foreground, vv result); //result to foreground Mat background = image - foreground; rectangle(image, rect, cv::scalar(55, v 55, 55), ); // kép, tégla, szín, vonalvastagság imshow("lena", image); imshow("hatter", background); imshow("eloter", foreground); for (;;) { int c = waitkey(3); if (c == 'q' c == 'Q') break; return ; 8
..4 Diszkrét Fourier transzformáció Legyen f periodikus valós függvény periódussal. A függvény értékei az f Δx=π/(n+) π x k = πk n + pontokban f(x k ) [, π) k =,,. n Egyértelműen meghatározható a Az x k pontokra n f x = c j e ijx = c j (cos(jx) + i sin(jx)) i = j= j= n f (x k ) = c j e ijx k k =,, n i = j= n 8
Jelölje π i w = e n+ az n+. komplex egységgyököt! Ekkor e ix k = e ikπ f (x k ) = n j= f (x k ) = n j= c j e ijx k = c j e ijx k k =,, n i = n j= c j (w k ) j n+ = w k k =,,, n Egyenletrendszer c j komplex ismeretlenekre együttható mátrixa Vandermonde n Létezik pontosan egy megoldás. Legyen a komplex n+ dimenziós vektorok skaláris szorzata x, y = n k= x k y k 83 π n + így bármely f=[f(x ), f(x ), f(x n )] és g=[g(x ), g(x ), g(x n )] vektorok esetére f, g = w w n w w n w n n k= w n n f(x k ) g(x k ) Φ n x = det(h) = w k= c k x k f Δx=π/(n +) x x x x n n x n x n n π
..4. Diszkrét Fourier transzformáció számítása Bármely f=[f(x ), f(x ), f(x n )] és g=[g(x ), g(x ), g(x n )] vektorok esetére e ilx = [e ilx, e ilx, e ilx n] és e ijx =[e ijx, e ijx, e ijx n] vektorokra (i =-) e ilx, e ijx = n k= e ilx merőleges e ijx e i(l j)x k = n k= (w l j ) k = ha l j Ortogonális bázis n + ha l = j ha l j Hiszen mértani sor összege (l j) és w l-j egységgyök w n+ = Az x k pontokra a diszkrét trigonometrikus interpoláció f (x k ) = w l j n+ w l j Az f=[f(x ), f(x ), f(x n )] vektort szorozzuk e -ilx = [e -ilx, e -ilx, e -ilx n] vektorral! n k= n j= f(x k )e ilx k = c j e ijx k k =,, n i = n n k= j= c j e ijx ke ilx k = c l = (f, eilx ) n + = (f, ei(n++l)x ) n + n j= c j n k= e ix k(j l) = (n + )c l e ni e i = c n++l periodikusak n + re f(c,, C n ) 84
..4. FFT Legyen n= m -! Számítsuk ki a összeget! Φ j = n k= a k w kj j =,, n Ha ismertek az f(x k )-k, a c j -ket határozzuk meg (analízis), akkor a k = f(x k) Ha ismertek a c j -k, az f(x k )-kat határozzuk meg (szintézis), akkor a k = c k Ο(n ) művelet - n együttható n művelettel. Bontsuk k-t páros (l) és páratlan (l+) tagokra! jelölje n = m- -! n+ n a lw lj + n a l+w l+ j = n a l(w ) lj +w j n a l+(w ) lj Φ j = l= l= l= l= Φ j = Ψ j + w j Χ j j =,, n Ψ(j)-t és Χ(j)-t csak fele annyi indexre kell kiszámítani j=,, n mert (w ) j+n + = (w ) j+n+ = (w ) j És így tovább Q m = * Q m- + m két szumma + m szorzás 85
A műveletek száma Q m = m m Q m = * Q m- + m két szumma + m szorzás Bizonyítás teljes indukcióval Q =, Ha Q m- =(m-) m-, akkor Q m =(m-) m- + m =m m Mivel m =n+; /log () m * log ()=log (n+) m= log (n+) a műveletek száma tehát (n+) * log (n+) O(n * log (n)) matematikai művelet < O(n ) Ha nem hatvány, akkor n+=3 * m, 5 * m, 86
..4.3 Fourier sor/transzformáció értelmezés Vektorok az R 3 -ben 3 a, b = a i b i skaláris szorzat i= a, b = a b z f z R 3 f (x f, y f, z f ) a = a, a norma f = x f i + y f j + z f k k x f = f, i ; y f = f, j ; z f = f, k ; L-periodikus függvények I L N általánosan I L L a, b = abdx skaláris szorzat L i j y f x f y x I z L f (C,, C j,, C ) a, b = a b a = a, a norma N f = C j e jxi f C k e kxi j= k= N e i e i e ji C j = f, e jxi ; j (, ) i = I z L f (C,, C j,, C ) C k = f, e kxi ; k ( N, N) i = e i e Ni e i e ki e Ni f(c N,, C j,, C N ) 87
..4.4 Diszkrét Fourier transzformáció (FFT algoritmussal) Y = fft(x) - X jel diszkrét FFT transzformáltja X = ifft(y) - Y jel diszkrét inverz FFT transzformáltja Fs = 7; % minta frekvencia t = -.5:/Fs:.5; % az idõvektor L = length(t); % a jel hossza X = exp(-*t.^); % a jel impulzus f=figure('name',... % grafikus ablak 'A jel idõtartományban', 'NumberTitle','off'); plot(t,x) shg n = ^nextpow(l); % a legközelebbi hatvány Y = fft(x,n); % FFT n pontra f = Fs*(:(n/))/n; % a kirajzolt frekvenciák P = abs(y/(n/)); % a Fourier transzformált valós értékekkel f=figure ('Name',... % grafikus ablak 'Fourier transzfomált', 'NumberTitle','off'); plot(f,p(:n/+)) f3=figure ('Name',... % grafikus ablak 'A vissza-transzfomált jel', 'NumberTitle','off'); ix = ifft(y) % inverz FFT transzformáció plot(t,ix) shg 88
..4.5 D-s diszkrét Fourier-transzformáció fk, l k M, l N f k,l k m +, l n + D n,m N M N M k l f k,l e mk i M e nl i N f k,l M N m n D n,m e ikm M e i ln N A Fourier transzformált abszolút értéke logaritmikus léptékben képként. Az (,) indexű tag tartalmazza az átlagos világosságot. D n,m értékek periodikusak N-re, M-re D n+n,m =D n,m, D n,m+m =D n.m D, és D N/,M/ valósak N/*M/ adat egyértelműen meghatározza A (k,l), a (k,n-l), az (M-k,l) és az (M-k,N-l) tagok azonosak 89
,,,,M/-,M/,,,, N/-, N/-,M/- N/-,M/ N/-, N/, N/,M/- N/,M/ N/, N/-,,,M/-,M/, N/,M/ N/, N/, N/,M/- N/-,,M/,,,M/-,M/,,,,,M/-,,, N/-,M/ N/-, N/-, N/-,M/- 9
..4.6 Képkezelés frekvencia-tartományban. Meghatározzuk a kép Fourier transzformáltját.. A Fourier transzformált szűrésével egyes komponenseket erősítünk, illetve csillapítunk. 3. Inverz Fourier transzformációval előállítjuk a módosított képet. Aluláteresztő szűrés zajcsökkentés, lágyítás Felüláteresztő szűrés A kis síkfrekvenciák kiszűrésével élkeresés, Nagy síkfrekvenciák erősítésével élesítés void dft(inputarray src, OutputArray dst, int flags=, int nonzerorows=) src input tömb valós vagy komplex. dst output tömb - a flagtől függő méret. flags DFT_INVERSE inverz D, D transzformáció a deafult transzformáció helyett. DFT_SCALE az eredmény skálázva (a tömbelemek számával osztva) DFT_INVERSE. DFT_ROWS transzformáció soronként (több transzformáció egyszerre) DFT_COMPLEX_OUTPUT D vagy D valós mátrix transzformáció komplex eredménnyel. DFT_REAL_OUTPUT D vagy D complex mátrix inverz transzformáció valós eredménnyel. nonzerorows ha nem nulla, akkor csak ez első nonzerorows eltérően kezelve. 9
#include "stdafx.h" #include <stdio.h> #include <opencv/opencv.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { VideoCapture cap; cap.open(); // default kamera az első Mat frame,gray,padded, magi, complexi, tmp, complexii; for (;;) { cap >> frame; if (frame.empty()) continue; imshow("picture", frame); if (frame.empty()) continue; cvtcolor(frame, gray, COLOR_BGRGRAY); imshow("gray", gray); int m = getoptimaldftsize(gray.rows); int n = getoptimaldftsize(gray.cols); // a határokra //az optimális méret copymakeborder(gray, padded,, m - gray.rows,, n - gray.cols, BORDER_CONSTANT, Scalar::all()); Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_3F) ; merge(planes,, complexi); // complex sík dft(complexi, complexi); // DFT logaritmikus skálában log( + sqrt(re(dft(i))^ + Im(DFT(I))^)) split(complexi, planes); // planes[] = Re(DFT(I), planes[] = Im(DFT(I)) magnitude(planes[], planes[], planes[]);// planes[] = magnitude magi = planes[]; magi += Scalar::all(); // a logaritmikus skála log(magi, magi); magi = magi(rect(,, magi.cols & -, magi.rows & -)); int cx = magi.cols / ; int cy = magi.rows / ; 9
return ; Mat q(magi, Rect(,, cx, cy)); // Átrendezés Mat q(magi, Rect(cx,, cx, cy)); Mat q(magi, Rect(, cy, cx, cy)); Mat q3(magi, Rect(cx, cy, cx, cy)); tmp; q.copyto(tmp); q3.copyto(q); tmp.copyto(q3); q.copyto(tmp); q.copyto(q); tmp.copyto(q); normalize(magi, magi,,, CV_MINMAX); imshow("spectrum", magi); Mat sz = Mat::zeros(complexI.rows, complexi.cols, CV_3FC); for (int i = ; i < complexi.rows; i++) for (int j = ; j < complexi.cols; j++) { if (i<.35*complexi.cols i>.65*complexi.cols j<.35*complexi.rows i <.65* complexi.rows) sz.at<float>(i, j) = ; else sz.at<float>(i, j) = ; complexi = complexi.mul(sz); dft(complexi, complexii, DFT_INVERSE + DFT_COMPLEX_OUTPUT); split(complexii, planes); magi = planes[]; normalize(magi, magi,,, CV_MINMAX); imshow("fftifft", magi); int c = waitkey(3); if (c == 'q' c == 'Q') break; 93
94
4.3.3 Alakfelismerés frekvenciasíkban Kép M int a Pozíció Háttér DFT ( Kép ) DFT ( M int a ) DFT ( Pozíció ) DFT ( Háttér ) DFT( Kép ) DFT( M int a ) DFT( Pozíció) DFT( Háttér ) DFT( M int a ) DFT( Pozíció) DFT( Kép ) DFT( M int a ) háttérzaj Pozíció DFT ( DFT( Kép ) DFT( M int a ) )
DFT(kép) DFT(minta) DFT(kép) DFT(Minta)
Képek információinak feldolgozása (3D) Példa : Az emberi test adatainak mérése 3D letapogatóval A mérési elv 97
98
. Pozíció-meghatározás síkban.. A sík-sík perspektíva bijekció Iteráció y O O x D A O η ζ O A C P C B 99
. Kalibráció
A piros kiszűrése után statisztikai osztályozás + súlypontok Regressziós Fourier-görbék a súlyponti koordinátarendszerben (Fourier-transzformált) i b i a a R n i i n i i sin cos ) ( N k k n i i k n i i k i b i a a R min sin cos.3 Kontúrok keresése
3
3 A térlátás Pinhole (tűlyuk) kamera modell Intrinsic: A kamera belső felépítését leíró paraméterek. Extrinsic: A kamera világbeli helyzetét leíró paraméterek. 3. Intrinsic paraméterek Fókusztávolság: fx, fy (nem négyzet pixel) Optikai középpont (principle point): c x, c y Lencsetorzítás: Radiális: k, k, k 3 (paraméterek - hordó, vagy párna torzítást. ) Tangenciális: p, p a lencse nem lesz teljesen párhuzamos a képsíkkal 4
/ / Z Y Z X c f c f y y x x y y x x f c y ŷ f c x xˆ A leképezés: A pixel koordináták: y x r 6 3 4 6 3 4 r k r k r k ŷ dr r k r k r k xˆ dr y x Radiális torzítás: Tangenciális torzítás: y x p y r p dp x r p xy p dp y x ˆˆ ˆ ˆ ˆˆ y y x x dp dr y y dp dr x x ˆ ~ ˆ ~ A koordináták: ξ η x y z P P k C P x P y P xy O Π x Π y s f OC 5
3. Extrinsic paraméterek Orientáció: R a kamera világbeli nézeti iránya. (bázistranszformációval) z z z y y y x x x w v u w v u w v u R z y x t t t t Pozíció: t a kamera világbeli pozíciója 6
3.3 Epipoláris geometria double calibratecamera(inputarrayofarrays objectpoints, InputArrayOfArrays imagepoints, Size imagesize, InputOutputArray cameramatrix, InputOutputArray distcoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags=, TermCriteria criteria=termcriteria( TermCriteria::COUNT+TermCriteria::EPS, 3, DBL_EPSILON) ) A kamera-paraméterek becslése. void calibrationmatrixvalues(inputarray cameramatrix, Size imagesize, double aperturewidth, double apertureheight, double& fovx, double& fovy, double& focallength, Pointd& principalpoint, double& aspectratio) Lehetséges kamera karakterisztikák bool findchessboardcorners(inputarray image, Size patternsize, OutputArray corners, int flags=calib_cb_adaptive_thresh + CALIB_CB_NORMALIZE_IMAGE ) A sakktábla sarkok void cornersubpix(inputarray image, InputOutputArray corners, Size winsize, Size zerozone, TermCriteria criteria) A sakktábla sarkok pontosítása void computecorrespondepilines(inputarray points, int whichimage, InputArray F, OutputArray lines) Epipoláris egyenes 7