CHƯƠNG 6 Image Transforms doc

35 565 6
CHƯƠNG 6 Image Transforms doc

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

CHƯƠNG 6 Image Transforms Tổng quan Trong chương ta trước đề cập nhiều thứ khác nhau bạn có thể làm với một image. Chính yếu của các operator được trình bày được dùng enhance, modify, hay ngược lại “process” một image thành một ảnh tương tự nhưng mới. Trong chương này ta sẽ quan sát image transforms, mà các methods để thay đổi một image thành một biểu diễn thay thế của data. Chẳng hạn hầu hết example phổ biến của một transform là gì đó giống Fourier transform, mà trong đó image được chuyển thành biểu diễn thay thế của data trong image gốc. Kết quả của operation này được lưu trong một OpenCV “image” structure, nhưng các “pixel” riêng trong image mới này biểu diễn các thành phần spectral của input gốc hơn là các thành phần không gian ta được dùng để nghĩ về. Có một số trong các transform hữu ích mà đến lặp lại trong computer vision. OpenCV cung cấp các thực hiện hoàn chỉnh của vài trong những cái phổ biến cũng như dựng các block để giúp bạn thực hiện các image transform riêng. Convolution Convolution là cơ sở của nhiều trong các transformation mà ta thảo luận trong chương này. Về khái quát, thuật ngữ này có nghĩa ta làm mọi phần của một image. Trong ý thức này, nhiều trong các operation ta xem xét trong chương 5 có thể cũng được hiểu như các trường hợp đặc biệt của tiến trình tổng quát hơn của convolution. Điều một convolution cụ thể “làm” được xác định bởi dạng của Convolution kernel được dùng. Kernel này thực sự chỉ là một fixed size array của các hệ số cùng với một anchor point trong array đó, mà điển hình được đặt ở tâm. Size của array* được gọi support của kernel. Figure 6-1 mô tả một 3-by-3 convolution kernel với anchor đặt ở center của array. Value của convolution ở một điểm cụ thể được tính bởi đầu tiên đặt kernel anchor ở đỉnh của một pixel trên image với phần còn lại của kernel nằm chồng các local pixel tương ứng trong image. Cho mỗi kernel point, ta bây giờ có một value cho kernel ở điểm đó và một value cho image ở image point tương ứng. Ta nhân những cái này cùng nhau và cộng kết quả; kết quả này được đặt trong image kết quả ở vị trí tương ứng với vị trí của anchor trong input image. Tiến trình này được lặp lại cho mỗi point trong image bởi quét kernel qua toàn bộ image. Figure 6-1. Một 3-by-3 kernel cho một vi phân Sobel; lưu ý rằng anchor point ở tâm của kernel Ta có thể, dĩ nhiên, mô tả procedure này theo dạng của một phương trình. Nếu ta định nghĩa image là I(x, y), kernel là G(i, j) (trong đó 0 < i< Mi –1 và 0 < j < Mj –1), và điểm anchor được định vị ở (ai, aj) theo tọa độ trong kernel, thì convolution H(x, y) được định nghĩa bởi biểu thức sau: ∑ ∑ − = − = −+−+= 1 0 1 0 ),(),(),( i j M i M j ji jiGajyaixIyxH Nhận thấy rằng số các operation, tối thiểu ở cái nhìn đầu tiên, dường như là số các pixel trong image được nhận bởi số các pixel trong kernel.* Điều này có thể là nhiều tính toán và do đó không là thứ bạn muốn làm với vài “for” loop và nhiều pointer de-referencing. Trong những trường hợp như thế này, tốt hơn để OpenCV làm việc cho bạn và lấy thuận lợi của các tối ưu hiện được lập trình vào OpenCV. Cách OpenCV làm điều này là với cvFilter2D(): void cvFilter2D( const CvArr* src, CvArr* dst, const CvMat* kernel, CvPoint anchor = cvPoint(-1,-1) ); Ở đây ta tạo một matrix với size thích hợp, điền nó với các hệ số, và sau đó chuyển nó cùng nhau với các source và ảnh đíchs vào cvFilter2D(). Ta có thể cũng tùy chọn chuyển vào một CvPoint để nhận diện vị trí của center của kernel, nhưng value mặc định (bằng với cvPoint(-1,-1)) được hiểu như nhận biết ở center của kernel. Kernel có thể có size chẵn nếu anchor point của nó được định nghĩa; ngược lại, nó nên là size lẻ. Các src và dst images nên là cùng size. Một có thể nghĩ rằng src image nên lớn hơn dst để cho phép cho width và length thêm của convolution kernel. Nhưng các size của src và dst có thể là giống trong OpenCV vì, bởi mặc định, ưu tiên trong convolution OpenCV tạo các virtual pixel qua việc tái tạo qua biên của src image sao cho các pixel biên trong dst có thể được điền vào. Việc tái tạo được làm như input(–dx, y) = input(0, y), input(w + dx, y) = input(w – 1, y), và vân vân. Có vài thay thế với hành động mặc định này; ta sẽ thảo luận chúng trong phần tiếp. Ta chú ý rằng các hệ số của convolution kernel nên luôn luôn là các số floatingpoint. Điều này có nghĩa rằng bạn nên dùng CV_32FC1 khi cấp phát matrix đó. Convolution Boundaries Một vấn đề mà đến tự nhiện với các convolution là cách handle các biên. Ví dụ, khi dùng convolution kernel vừa mô tả, điều xảy ra khi point được convolved ở cạnh của image? Hầu hết các function tạo sẵn của OpenCV thực hiện dùng của cvFilter2D() phải handle điều này theo cách này hay cách khác. Tương tự, khi làm các convolution riêng, bạn sẽ cần biết cách giải quyết điều này hiệu quả. Giải pháp đến theo dạng của cvCopyMakeBorder() function, mà chép một image cho trước vào một image lớn hơn một tí và sau đó tự động đêm boundary theo cách này hay cách khác: void cvCopyMakeBorder( const CvArr* src, CvArr* dst, CvPoint offset, int bordertype, CvScalar value = cvScalarAll(0) ); Offset argument nói với cvCopyMakeBorder() nới để đặt copy của image gốc bên trong image đích. Điều hình, nếu kernel là N-by-N (cho N lẻ) thì bạn sẽ muốn một boundary mà là rộng (N – 1)/2 trên tất cả các cạnh hay, tương đương, một image mà rộng hơn và cao hơn N – 1 so với gốc. Trong trường hợp này bạn nên đặt offset thành cvPoint((N-1)/2,(N-1)/2) sao cho biên sẽ là chẵn trên tất cả các cạnh.* Kiểu border có thể là một trong IPL_BORDER_CONSTANT hay IPL_BORDER_REPLICATE (xem Figure 6-2). Trong trường hợp đầu tiên, value argument sẽ được hiểu như value mà với tất cả pixels trong boundary nên được đặt. Trong trường hợp thứ hai, row hay column ở cạnh của gốc được tái tạo thành cạnh của image lớn hơn. Lưu ý rằng border của pattern image kiểm tra là gì đó huyền ảo (kiểm tra image trên phải trong Figure 6-2); trong image mẫu kiểm tra, có một border tối rộng một pixel ngoại trừ nơi các circle pattern đến gần border ở đó nó chuyển thành trắng. Có hai border types khác nhau được định nghĩa, IPL_BORDER_REFLECT và PL_BORDER_WRAP, mà không thực hiện ở thời điểm này trong OpenCV nhưng có thể được hỗ trợ trong tương lai. Figure 6-2. Mở rộng image border. Cộ trái cho thấy IPL_BORDER_CONSTANT nới một zero value được dùng để điền cho các border. Cột phải cho thấy IPL_BORDER_REPLICATE nơi border pixels được tái tạo theo các hướng ngang và dọc Ta đề cập trước đây rằng, khi bạn làm các lời gọi đến các OpenCV libraery functions mà thực hiện convolution, các library function này gọi cvCopyMakeBorder() để lấy việc của chúng làm. Trong hầu hết các trường hợp border type được gọi là IPL_BORDER_REPLICATE, nhưng đôi khi bạn sẽ không muốn nó được làm theo cách đó. Đâu là một dịp khác nơi bạn có thể muốn dùng cvCopyMakeBorder(). Bạn có thể tạo một image lớn hơn một tí với border bạn muốn, gọi bất cứ routine trên image đó, và sau đó cắt lại phần bạn quan tâm ban đầu. Cách này, định biên tự động của OpenCV sẽ không ảnh hưởng các pixel bạn quan tâm. Gradients và Sobel Derivatives Một trong các convolution hầu hết cơ bản và quan trọng là tính các đạo hàm (hay xấp xỉ chúng). Có nhiều cách để làm điều này, nhưng chỉ vài được phù hợp tốt cho trường hợp được cho. Nhìn chung, hầu hết operator phổ biến dùng để biểu diễn vi phân là Sobel derivative [Sobel68] operator (xem Figures 6-3 và 6-4). Các Sobel operator tồn tại cho bất kỳ bậc đạo hàm cũng như for các vi phân riêng phần hỗn hợp (chẳng hạn yx∂∂∂ / 2 ). Figure 6-3. Hiệu ứng của Sobel operator khi dùng với xấp xỉ một vi phân đầu tiên theo x-dimension cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size = 3 ); Ở đâu, src và dst là image input và output của bạn, và xorder và yorder là các thứ tự của vi phân. Điển hình bạn sẽ dùng 0, 1, hay hầu hết ở 2; một 0 value nhận biết không vi phân theo hướng đó.* aperture_size parameter nên là lẻ và là width (và height) của square filter. Hiện tại, aperture_sizes 1, 3, 5, và 7 được hỗ trợ. Nếu src là 8-bit thì dst phải có độ sâu IPL_DEPTH_16S để tránh tràn. Sobel derivatives có đặc tính tốt mà chúng có thể được định nghĩa cho các kernel ở bất kỳ size, và những kernel này có thể được xây dựng nhanh chóng và lặp lại. Các kernel lớn hơn cho một xấp xỉ tốt hơn cho vi phân vì các kernel nhỏ hơn rất nhậy với noise. Figure 6-4. The effect of the Sobel operator khi used to approximate a đầu tiên derivative in the y-dimension Để hiểu điều này chính xác hơn, ta phải thấy rõ rằng một Sobel derivative không thực sự một vi phân. Điều này là vì Sobel operator được định nghĩa trên một không gian rời rạc. Điều Sobel operator thực sự biểu diễn là một điều chỉnh thành một đa thức. Mà là, Sobel derivative của bậc hai theo x-direction không thực sự là vi phân thứ hai; nó là điều chỉnh tại chỗ thành một hàm parabolic. Điều này giải thích một nguyên nhân có thể muốn dùng một kernel lớn hơn: mà kernel lớn hơn sẽ tính điều chỉnh trên số lớn hơn các pixel. Scharr Filter Thật ra, có nhiều cách để thích hợp một vi phân trong trường hợp của một discrete grid. Phía dưới của xấp xỉ dùng cho Sobel operator mà nó ít chính xác cho các kernel nhỏ. Cho các kernel lớn, nơi nhiều điểm được dùng trong xấp xỉ, vấn đề này là ít ý nghĩa. Sự không chính xác này không cho thấy trực tiếp cho các X và Y filters được dùng trong cvSobel(), vì chúng chính xác được sắp với các trục x- và y Sự khó khăn đến khi bạn muốn làm các đo lường image mà là các xấp xỉ của các đạo hàm hướng (chẳng hạn hướng của image gradient bởi dùng arctangent của các đáp ứng y/x filter). Để đặt điều này trong ngữ cảnh, một example cụ thể nơi bạn có thể muốn các đo lường image của kiểu này sẽ ở tiến trình thu thập thông tin hình dáng từ một object bởi tập hợp một histogram của các góc gradient quanh object. Chẳng hạn một histogram là cơ sở mà trên nhiều bộ phân loại hình dáng chung được huấn luyện và hoạt động. Trong trường hợp này, các đo lường không chính xác của gradient angle sẽ giảm hiện suất nhận diện của bộ phân loại. Cho một 3-by-3 Sobel filter, các không chính xác là rõ ràng hơn gradient angle từ ngang hay dọc. OpenCV để ý sự không chính xác này cho các bộ lọc Sobel nhỏ (nhưng nhanh) 3-by-3 bởi một dùng một ít mờ của giá trị aperture_size đặc biệt CV_SCHARR trong cvSobel() function. Scharr filter không chỉ nhanh mà còn chính xác hơn Sobel filter, do đó nó sẽ luôn luôn được dùng nếu bạn muốn làm các đo lường image dùng một 3-by-3 filter. Các hệ số filter cho Scharr filter được thấy trong Figure 6-5 [Scharr00]. Figure 6-5. 3-by-3 Scharr filter dùng flag CV_SHARR Laplace OpenCV Laplacian function (đầu tiên được dùng trong vision bởi Marr [Marr82]) thực hiện một tương tự rời rạc của Laplacian operator:* 2 22 )( y f x f fLaplace e ∂ ∂ + ∂ ∂ = Vì Laplacian operator có thể được định nghĩa theo các thuật ngữ của đạo hàm bậc hai, bạn có thể giả thiết rằng thực hiện rời rạc làm gì đó như đạo hàm Sobel bậc hai. Thực ra nó làm, và thật ra OpenCV thực hiện Laplacian operator dùng các Sobel operator trực tiếp trong tính toán của nó. void cvLaplace( const CvArr* src, CvArr* dst, int apertureSize = 3 ); cvLaplace() function lấy các ảnh nguồn và đích như thường cũng như một aperture size. Nguồn có thể là một trong một 8-bit (unsigned) image hay a 32-bit (floating-point) image. Đích phải là một 16-bit (signed) image hay 32-bit (floating-point) image. Aperture này chính xác là giống aperture xuất hiện trong các đạo hàm Sobel và, về hiệu quả, cho size của vùng mà trên đó các pixel được lấy mẫu trong tính toán của đạo hàm bậc hai. Laplace operator có thể được dùng trong muôn vàn hoàn cảnh. Một ứng dụng chung là dò các “blob.” Nhờ lại dạng của Laplacian operator mà là tổng các đạo hàm bậc hai theo trục x và trục y. Điều này có nghĩa rằng một điểm đơn hay bất kỳ blob nhỏ (nhỏ hơn aperture) mà được bao quanh bởi các giá trị cao hơn sẽ hướng đến cực đại function này. Ngược lại, một điểm hay blob nhỏ mà được bao quanh bởi các giá trị thấp hơn sẽ hướng đến tối đa phần âm của function này. Với điều này trong đầu, Laplace operator có thể cũng được dùng như một kiểu của edge detector. Để thấy cách điều này được làm, lưu ý đạo hàm đầu tiên của một function, mà sẽ (dĩ nhiên) là lớn bất kể function là thay đổi nhanh. Quan trọng đều, nó sẽ phát triển nhanh như ta tiếp cận một sự không liên tục giống cạnh và co rút nhanh như ta chuyển qua sự không liên tục. Do đó đạo hàm sẽ ở cực đại địa phương đâu đó bên trong dải này. Do đó ta có thể quan sát các số 0 của đạo hàm bậc hai cho các vị trí của cực đại địa phương như thế. Hiểu không? Các cạnh trong ảnh gốc sẽ là những 0 của Laplacian. Không may, cả các cạnh quan trọng và ít s nghĩa sẽ là những số 0 của Laplacian, nhưng điều này không là một vấn đề vì ta có thể đơn giản lọc ra các pixel mà cũng có các giá trị lớn của đạo hàm đầu tiên (Sobel). Figure 6-6 cho thấy một ví dụ dùng Laplacian trên một image cùng nhau với các chi tiết của đạo hàm đầu tiên và bậc hai và các zero crossing của chúng. Canny Method vừa được mô tả để tìm các cạnh được tinh chỉnh xa hơn bởi J. Canny năm 1986 thành cái mà bây giờ phổ biến được gọi là Canny edge detector [Canny86]. Một trong các khác biệt giữa Canny algorithm và thuật toán dựa Laplace đơn giản hơnvới phần trước là, trong thuật toán Canny, các đạo hàm bậc một được tính theo x và y và sau đó kết hợp thành bốn đạo hàm hướng. Các điểm nơi những đạo hàm hướng này là cực trị địa phương sau đó là các ứng viên cho tập hợp thành các cạnh. Figure 6-6. Laplace transform (trên phải) của racecar image: zooming in trên bánh (vòng tròn trắng) và lưu ý chr hướng x, ta thấy mô tả (qualitative) của sự sáng cũng như đạo hàm bậc một và bậc hai (thấp hơn ba cell); những số 0 trong đạo hàm bậc hai tương ứng vứi các cạnh, và 0 tương ứng đạo hàm bậc một lớn là một cạnh mạnh Tuy nhiên, hầu hết hướng mới ý nghĩa với thuật toán Canny là nó cố tập hợp các pixel ứng viên cạnh riêng rẽ thành các contour.* những contours này được hình thành bởi áp dụng một hysteresis threshold cho các pixel. Điều này có nghĩa rằng có hai thresholds, một trên hơn và một thấp hơn. Nếu một pixel có gradient lớn hơn upper threshold, thì nó được chấp nhận như một edge pixel; nếu một pixel bên dưới lower threshold, nó bị loại. Nếu gradient của pixel ở giữa các threshold, thì nó được chấp nhậnchỉ nếu nó được nối với một pixel mà trên threshold cao. Canny khuyến cáo một ratio của high:low threshold giữa 2:1 và 3:1. Các hình 6-7 và 6-8 cho thấy các kết quả của áp dụng cvCanny() với một mẫu kiểm tra và một ảnh dùng các high:low hysteresis threshold ratios 5:1 và 3:2, tương ứng. void cvCanny( const CvArr* img, CvArr* edges, double lowThresh, double highThresh, int apertureSize = 3 ); Figure 6-7. Các kết quả của Canny edge detection cho hai ảnh khác nhau khi các high và low thresholds được đặt thành 50 và 10, tương ứng cvCanny() function mong một input image, mà phải là grayscale, và một output image, mà phải cũng là grayscale (nhưng mà sẽ thực sự là một Boolemột image). Hai arguments tiếp là các low và high thresholds, và argument cuối là một aperture khác. Như thường, đây là aperture được dùng bởi các Sobel derivative operators mà được gọi bên trong của thực hiện cvCanny(). Hough Transforms Hough transform* là một method để tìm các đường thẳng, đường tròn, hay các dạng đơn giản trong một image. Hough transform ban đầu là một biến đổi thẳng, mà là cách tương đối nhanh để tìm một ảnh nhị phân cho các đường thẳng. Transform này có thể được tổng quát xa hơn cho các trường hợp hơn chỉ cho các đường đơn giản. Hough Line Transform Lý thuyết cơ bản của Hough line transform là bất kỳ điểm trong ảnh nhị phân có thể là phần của vài tập các đường có thể. Nếu ta tham số hóa mỗi đường bởi, ví dụ, một slope a và một intercept b, thì điểm a trong một ảnh gốc được biến đổi thành một quỹ tích các điểm trong mặt phẳng (a, b) tương ứng với tất cả các đường đi qua điểm đó (xem Figure 6-9). Nếu ta chuyển mọi nonzero pixel trong input image thành một tập các điểm trong output image và tộng trên tất cả các đóng góp, thì các đường mà xuất hiện trong input (chẳng hạn (x, y) plane) image sẽ xuất hiện như cực trị địa phương trong output (chẳng hạn (a, b) plane) image. Vì ta đang cộng các hợp thành từ mỗi điểm, (a, b) plane nhìn chung được gọi là accumulator plane. Figure 6-8. các kết quả của Canny edge detection cho hai image khác nhau khi các high và low thresholds được đặt thành 150 và 100, tương ứng Điều có thể xảy ra với bạn rằng dạng slope-intercept không thực sự là cách tốt nhất để biểu diễn tất cả các đường đi qua một điểm (vì mật độ khác nhau đáng kể của các đường như một function của slope, và sự thật liên qua rằng interval của các slope có thể đi từ –∞ đến +∞). Nó là cho nguyên nhân này mà sự tham số hóa thực của transform image dùng trong tính toán số là gì đó khác. Sự tham số hóa ưa thích hơn biểu diễn mỗi đường như một điểm trong tọa độ cực (ρ, θ), với đường ngầm định bằng đầu là đường đi qua điểm nhận biết nhưng vuông góc với radial từ gốc đến điểm đó (xem Figure 6-10). Phương trình cho một đường thẳng là : )sin()cos( θθ yxp += Figure 6-9. Hough line transform tìm thấy nhiều đường trong mỗi image; vài trong các đường được thấy như mong đợi, nhưng những cái khác có thể không Figure 6-10. Một point (x0, y0) trong image plane (panel a) ngụ ý nhiều đường mỗi cái được tham số bởi một ρ và θ (panel b) khác nhau; những đường này mỗi cái được ngụ ý các điểm trong (ρ, θ) plane, mà được lấy cùng nhau hình thành đường cong hình dáng đặc tính (panel c) Thuật toán Hough transform OpenCV không thực hiện tính toán này rõ ràng với user. Thay vào đó, nó đơn giản trả về cực trị địa phương trong (ρ, θ) plane. Tuy nhiên, bạn sẽ cần hiểu tiến trình này để hiểu các argument cho OpenCV Hough line transform function. OpenCV hỗ trợ hai kiểu khác nhau của Hough line transform: standard Hough transform (SHT) [Duda72] và progressive probabilistic Hough transform (PPHT).* SHT là thuật toán ta vừa xem xét. PPHT là một biến thể của thuật toán này mà, cùng với các thứ khác, tính một mở rộng cho các đường cụ thể thêm vào đó với hướng (như được thấy trong Figure 6-11). Nó là “có khả năng” vì, hơn việc lũy kế mọi điểm có khả năng trong mặt phẳng lũy kế, nó lũy kế chỉ một phần của chúng. Ý tưởng là nếu đỉnh sẽ là đủ cao đại khái, sau khi đánh nó chỉ một phần của thời gian sẽ để để tìm thấy nó; Kết quả của ước đoán này có thể là giảm thực chất trong thời gian tính. Cả hai thuật toán này được truy cập với cùng OpenCV function, qua các phương tiện của vài các argument phụ thuộc vào method mà đang được dùng. CvSeq* cvHoughLines2( [...]... từng cái một Exercises 1 Dùng cvFilter2D() để tạo một filter mà dò chỉ các đường 60 độ trong một image Hiển thị các kết quả trên một cảnh thú vị 2 Các lõi riêng biệt Tạo một 3-by-3 Gaussian kernel dùng các hàng [(1/ 16, 2/ 16, 1/ 16) , (2/ 16, 4/ 16, 2/ 16) , (1/ 16, 2/ 16, 1/ 16) ] và với một điểm neo ở giữa a Chạy kernel này trên một image và hiện thị các kết quả b Bây giờ tạo các hai kerner một chiều với các neo... diễn Example 6- 1 cho thấy một program ví dụ dùng cvHoughCircles() Example 6- 1 Dùng cvHoughCircles để return một chuỗi các đường tròn tìm thấy trong một grayscale image #include #include #include int main(int argc, char** argv) { IplImage* image = cvLoadImage( argv[1], CV_LOAD _IMAGE_ GRAYSCALE ); CvMemStorage* storage = cvCreateMemStorage(0); cvSmooth (image, image, CV_GAUSSIAN,... image phải có size (W + 1)-by-(H + 1).* Một integral image sum có dạng: sum( X , Y ) = ∑∑ image( x, y ) x≤ X y ≤Y sqsum image tùy chọn là tổng các bình phương: sum( X , Y ) = ∑∑ (image( x, y )) 2 x≤ X y ≤Y và tilted_sum giống sum ngoại trừ rằng nó để image quay 45 độ: titl _ sum( X , Y ) = ∑ ∑ image( x, y) y ≤Y abs ( x − X )≤ y Dùng những integral image này, một có thể tính sums, means, và các vi phân... độ phức tạp tính O(1)) Figure 6- 19 Ảnh 7-by-5 image của Figure 6- 18 được thấy như số ở bên trái (với gốc giả thiết là trên trái) và được chuyển thành integral image bên phải Distance Transform Biến đổi khoảng cách của một image được định nghĩa như một image mới mà trong đó mỗi output pixel được đặt thành một value bằng với khoảng cách đến zero pixel gần nhất trong input image Điều tức thời hiển nhiên... cần là image; chúng có thể là các matrix, nhưng trong thực tế, chúng thường là các image. ) Khi input image là 8-bit unsigned, sum hay tilted_sum có thể là các array 32-bit integer hay floating-point Cho tất cả các trường hợp, sum hay tilted_sum phải là giá trị floating-point (một trong 32- hay 64 -bit) Kết quả “images” phải luôn luôn là floating-point Nếu input image có size W-by-H, thì các output image. .. CvSeq* results = cvHoughCircles( image, storage, CV_HOUGH_GRADIENT, 2, image- >width/10 ); for( int i = 0; i < results->total; i++ ) { float* p = (float*) cvGetSeqElem( results, i ); CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] ) ); cvCircle( image, pt, cvRound( p[2] ), CV_RGB(0xff,0xff,0xff) ); } cvNamedWindow( “cvHoughCircles”, 1 ); cvShowImage( “cvHoughCircles”, image) ; cvWaitKey(0); } Điều đáng... tương ứng srcTri[] Example 6- 2 An affine transformation // Usage: warp_affine // #include #include int main(int argc, char** argv) { CvPoint2D32f srcTri[3], dstTri[3]; CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1); CvMat* warp_mat = cvCreateMat(2,3,CV_32FC1); IplImage *src, *dst; if( argc == 2 && ((src=cvLoadImage(argv[1],1)) != 0 )) { dst = cvCloneImage( src ); dst->origin =... được thấy trong Figure 6- 17 Figure 6- 17 Ví dụ Log-polar trên con nai sừng tấm với biến đổi tâm ở vòng tròn trắng bên trái; output bên phải Example 6- 4 Log-polar transform example // logPolar.cpp : định nghĩa the entry point for the console application // #include #include int main(int argc, char** argv) { IplImage* src; double M; if( argc == 3 && ((src=cvLoadImage(argv[1],1)) != 0... atof(argv[2]); IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3 ); IplImage* src2 = cvCreateImage( cvGetSize(src), 8, 3 ); cvLogPolar( src, dst, cvPoint2D32f(src->width/4,src->height/2), M, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS ); cvLogPolar( dst, src2, cvPoint2D32f(src->width/4, src->height/2), M, CV_INTER_LINEAR | CV_WARP_INVERSE_MAP ); cvNamedWindow( “log-polar”, 1 ); cvShowImage( “log-polar”,... image Multiply them và take the inverse Fourier transform of kết quảs What have bạn achieved? As the filters get bigger, bạn sẽ tìm thấy that working in the Fourier space is much faster than in the normal space 14 Load an interesting image, convert it to grayscale, và then take an integral image of it bây giờ tìm thấy vertical và horizontal edges in the image by dùng the properties of an integral image . { IplImage* image = cvLoadImage( argv[1], CV_LOAD _IMAGE_ GRAYSCALE ); CvMemStorage* storage = cvCreateMemStorage(0); cvSmooth (image, image, CV_GAUSSIAN, 5, 5 ); CvSeq* results = cvHoughCircles( image, storage, CV_HOUGH_GRADIENT, 2, image- >width/10 ); for(. CHƯƠNG 6 Image Transforms Tổng quan Trong chương ta trước đề cập nhiều thứ khác nhau bạn có thể làm với một image. Chính yếu của các operator được trình. đặt trong image kết quả ở vị trí tương ứng với vị trí của anchor trong input image. Tiến trình này được lặp lại cho mỗi point trong image bởi quét kernel qua toàn bộ image. Figure 6- 1. Một 3-by-3

Ngày đăng: 08/08/2014, 05:22

Tài liệu cùng người dùng

Tài liệu liên quan