Kiểu dữ liệu của hình ảnh trong python là gì?
Recognise morphometric problems (those dealing with the number, size, or shape of the objects in an image) Show
As computer systems have become faster and more powerful, and cameras and other imaging systems have become commonplace in many other areas of life, the need has grown for researchers to be able to process and analyse image data. Considering the large volumes of data that can be involved - high-resolution images that take up a lot of disk space/virtual memory, and/or collections of many images that must be processed together - and the time-consuming and error-prone nature of manual processing, it can be advantageous or even necessary for this processing and analysis to be automated as a computer program This lesson introduces an open source toolkit for processing image data. the Python programming language and the scikit-image ( 32) library. Với thiết kế thử nghiệm cẩn thận, mã Python có thể là một công cụ mạnh mẽ để trả lời nhiều loại câu hỏi khác nhauUses of Image Processing in ResearchAutomated processing can be used to analyse many different properties of an image, including the distribution and change in colours in the image, the number, size, position, orientation, and shape of objects in the image, and even - when combined with machine learning techniques for object recognition - the type of objects in the image Some examples of image processing methods applied in research include
With this lesson, we aim to provide a thorough grounding in the fundamental concepts and skills of working with image data in Python. Most of the examples used in this lesson focus on one particular class of image processing technique, morphometrics, but what you will learn can be used to solve a much wider range of problems MorphometricsMorphometrics involves counting the number of objects in an image, analyzing the size of the objects, or analyzing the shape of the objects. For example, we might be interested in automatically counting the number of bacterial colonies growing in a Petri dish, as shown in this image Chúng tôi có thể sử dụng xử lý hình ảnh để tìm các khuẩn lạc, đếm chúng và sau đó đánh dấu vị trí của chúng trên ảnh gốc, tạo ra một ảnh như thế này
As we move through this workshop, we will learn image analysis methods useful for many different scientific problems. These will be linked together and applied to a real problem in the final end-of-workshop capstone challenge Let’s get started, by learning some basics about how images are represented and stored digitally
Khái niệm cơ bản về hình ảnh
The images we see on hard copy, view with our electronic devices, or process with our programs are represented and stored in the computer as numeric abstractions, approximations of what we see with our eyes in the real world. Trước khi bắt đầu tìm hiểu cách xử lý hình ảnh bằng các chương trình Python, chúng ta cần dành thời gian để hiểu cách thức hoạt động của các trừu tượng này PixelsĐiều quan trọng là phải nhận ra rằng hình ảnh được lưu trữ dưới dạng mảng hình chữ nhật gồm hàng trăm, hàng nghìn hoặc hàng triệu “phần tử hình ảnh” rời rạc, còn được gọi là pixel. Mỗi pixel có thể được coi là một điểm vuông duy nhất của ánh sáng màu Ví dụ: hãy xem xét hình ảnh cây ngô con này, với diện tích hình vuông được chỉ định bởi hộp màu đỏ Now, if we zoomed in close enough to see the pixels in the red box, we would see something like this Lưu ý rằng mỗi ô vuông trong vùng hình ảnh phóng to - mỗi pixel - đều có một màu, nhưng mỗi pixel có thể có màu khác với các pixel lân cận. Nhìn từ xa, những pixel này dường như hòa trộn với nhau để tạo thành hình ảnh mà chúng ta thấy Làm việc với PixelNhư đã lưu ý, trong thực tế, các hình ảnh trong thế giới thực thường được tạo thành từ một số lượng lớn các pixel và mỗi pixel này sẽ là một trong số hàng triệu màu tiềm ẩn. Mặc dù chúng ta sẽ sớm xử lý các bức ảnh có độ phức tạp như vậy, nhưng hãy bắt đầu khám phá với 15 pixel trong ma trận 5 X 3 với 2 màu và tiến tới mức độ phức tạp đó
Đầu tiên, nhập khẩu cần thiết
Now that we have our libraries loaded, we will run a Jupyter Magic Command that will ensure our images display in our Jupyter document with pixel information that will help us more efficiently run commands later in the session 2With that taken care of, let’s load our image data from disk using the 52 function from the 53 module and display it using the 54 function from the 55 module. 56 is a Python library for reading and writing image data. 53 is specifying that we want to use version 3 of 56. Phiên bản này có lợi ích là hỗ trợ dữ liệu hình ảnh nD (đa chiều) nguyên bản (nghĩ về tập, phim)
7Bạn có thể đang nghĩ, “Cái đó trông hơi giống số tám, và tôi thấy hai màu nhưng làm sao nó chỉ có 15 pixel được”. The display of the eight you see does use a lot more screen pixels to display our eight so large, but that does not mean there is information for all those screen pixels in the file. All those extra pixels are a consequence of our viewer creating additional pixels through interpolation. It could have just displayed it as a tiny image using only 15 screen pixels if the viewer was designed differently While many image file formats contain descriptive metadata that can be essential, the bulk of a picture file is just arrays of numeric information that, when interpreted according to a certain rule set, become recognizable as an image to us. Our image of an eight is no exception, and 53 stored that image data in an array of arrays making a 5 x 3 matrix of 15 pixels. We can demonstrate that by calling on the shape property of our image variable and see the matrix by printing our image variable to the screen 9 0Vì vậy, nếu chúng ta có các công cụ cho phép chúng ta thao tác với các dãy số này, chúng ta có thể thao tác với hình ảnh. Thư viện 33 có thể đặc biệt hữu ích ở đây, vì vậy hãy thử điều đó bằng cách sử dụng kỹ thuật cắt mảng 33. Notice that the default behavior of the 54 function appended row and column numbers that will be helpful to us as we try to address individual or groups of pixels. First let’s load another copy of our eight, and then make it look like a zeroTo make it look like a zero, we need to change the number underlying the centremost pixel to be 1. With the help of those row and column headers, at this small scale we can determine the centre pixel is in row labeled 2 and column labeled 1. Using array slicing, we can then address and assign a new value to that position 4 5
More coloursUp to now, we only had a 2 colour matrix, but we can have more if we use other numbers or fractions. One common way is to use the numbers between 0 and 255 to allow for 256 different colours or 256 different levels of grey. Hãy thử điều đó 0We now have 3 colours, but are they the three colours you expected? They all appear to be on a continuum of dark purple on the low end and yellow on the high end. This is a consequence of the default colour map (cmap) in this library. You can think of a colour map as an association or mapping of numbers to a specific colour. Tuy nhiên, mục tiêu ở đây không phải là có một số cho mọi màu có thể, mà là có một chuỗi màu liên tục thể hiện cường độ tương đối. In our specific case here for example, 255 or the highest intensity is mapped to yellow, and 0 or the lowest intensity is mapped to a dark purple. Bản đồ màu tốt nhất cho dữ liệu của bạn sẽ khác nhau và có nhiều tùy chọn được tích hợp sẵn, nhưng lựa chọn mặc định này không tùy ý. A lot of science went into making this the default due to its robustness when it comes to how the human mind interprets relative colour values, grey-scale printability, and colour-blind friendliness (You can read more about this default colour map in a Matplotlib tutorial and an explanatory article by the authors). Thus it is a good place to start, and you should change it only with purpose and forethought. For now, let’s see how you can do that using an alternative map you have likely seen before where it will be even easier to see it as a mapped continuum of intensities. thang độ xám 1Ở trên, chúng tôi có chính xác cùng một ma trận dữ liệu cơ bản, nhưng ở thang độ xám. Zero maps to black, 255 maps to white, and 128 maps to medium grey. Ở đây, chúng tôi chỉ có một kênh duy nhất trong dữ liệu và sử dụng bản đồ màu thang độ xám để biểu thị độ chói hoặc cường độ của dữ liệu và tương ứng, kênh này được gọi là kênh độ sáng Even More ColoursĐây là tất cả tốt và tốt ở quy mô này, nhưng điều gì sẽ xảy ra khi thay vào đó chúng ta có một bức tranh phong cảnh thiên nhiên chứa hàng triệu màu sắc. Có một ánh xạ 1-1 của số thành màu như thế này sẽ không hiệu quả và việc điều chỉnh cũng như xây dựng các công cụ để thực hiện điều đó rất khó khăn. Thay vì số lớn hơn, giải pháp là có nhiều số hơn ở nhiều chiều hơn. Storing the numbers in a multi-dimensional matrix where each colour or property like transparency is associated with its own dimension allows for individual contributions to a pixel to be adjusted independently. This ability to manipulate properties of groups of pixels separately will be key to certain techniques explored in later chapters of this lesson. To get started let’s see an example of how different dimensions of information combine to produce a set of pixels using a 4 X 4 matrix with 3 dimensions for the colours red, green, and blue. Thay vì tải nó từ một tệp, chúng tôi sẽ tạo ví dụ này bằng cách sử dụng numpy 2 3Trước đây, chúng tôi có một số được ánh xạ tới một màu hoặc cường độ. Bây giờ chúng tôi đang kết hợp hiệu ứng của 3 số để đạt được một giá trị màu duy nhất. Hãy xem một ví dụ về điều đó bằng cách sử dụng hình vuông màu xanh lam ở cuối hàng thứ hai, có chỉ số [1, 3] 4kết quả này. array([ 7, 1, 110]) The integers in order represent Red, Green, and Blue. Nhìn vào 3 giá trị và biết cách chúng ánh xạ, có thể giúp chúng tôi hiểu tại sao nó có màu xanh lam. Nếu chúng ta chia mỗi giá trị cho 255, giá trị lớn nhất, thì chúng ta có thể xác định giá trị đó đang đóng góp bao nhiêu so với tiềm năng tối đa của nó. Thực tế, màu đỏ là 7/255 hoặc 2. 8 percent of its potential, the green is at 1/255 or 0. 4 phần trăm và màu xanh lam là 110/255 hoặc 43. 1 phần trăm tiềm năng của nó. Vì vậy, khi bạn trộn ba cường độ màu đó, màu xanh lam sẽ thắng với biên độ rộng, nhưng màu đỏ và xanh lục vẫn góp phần làm cho màu xanh lam hơi khác một chút so với 0,0,110 của riêng nó These colours mapped to dimensions of the matrix may be referred to as channels. Có thể hữu ích khi hiển thị độc lập từng kênh này để giúp chúng tôi hiểu điều gì đang xảy ra. Chúng tôi có thể làm điều đó bằng cách nhân biểu diễn mảng hình ảnh của chúng tôi với ma trận 1d có một cho kênh mà chúng tôi muốn giữ và số không cho phần còn lại 5 6 7Nếu chúng ta nhìn vào hình vuông [1, 3] phía trên trong cả ba hình, chúng ta có thể thấy từng đóng góp màu đó đang hoạt động. Lưu ý rằng có một số hình vuông trong hình màu xanh lam trông thậm chí còn đậm hơn hình vuông [1, 3]. Tuy nhiên, khi cả ba kênh được kết hợp, ánh sáng xanh lam của các ô vuông đó sẽ bị pha loãng bởi cường độ tương đối của màu đỏ và xanh lục được trộn lẫn với chúng Màu RGB 24-bitMô hình màu cuối cùng mà chúng tôi đã sử dụng, được gọi là mô hình RGB (Đỏ, Lục, Lam), là mô hình phổ biến nhất As we saw, the RGB model is an additive colour model, which means that the primary colours are mixed together to form other colours. Thông thường, lượng màu cơ bản được thêm vào được biểu thị dưới dạng một số nguyên trong phạm vi đóng [0, 255] như trong ví dụ. Do đó, có 256 lượng riêng biệt của mỗi màu cơ bản có thể được thêm vào để tạo ra màu khác. The number of discrete amounts of each colour, 256, corresponds to the number of bits used to hold the colour channel value, which is eight (28=256). Vì chúng ta có ba kênh với 8 bit cho mỗi kênh (8+8+8=24), đây được gọi là độ sâu màu 24 bit Bất kỳ màu cụ thể nào trong mô hình RGB đều có thể được biểu thị bằng bộ ba số nguyên trong [0, 255], tương ứng đại diện cho các kênh màu đỏ, lục và lam. Một số lớn hơn trong một kênh có nghĩa là có nhiều màu cơ bản hơn
Sau khi hoàn thành thử thách trước, chúng ta có thể xem xét một số ví dụ khác về màu RGB 24-bit một cách trực quan. Hình ảnh trong thử thách tiếp theo hiển thị một số tên màu, giá trị bộ ba RGB 24 bit của chúng và chính màu đó
Mặc dù độ sâu màu 24 bit là phổ biến nhưng vẫn có các tùy chọn khác. Chúng ta có thể có màu 8 bit (3 bit cho màu đỏ và xanh lá cây, nhưng chỉ có 2 cho màu xanh lam, cung cấp 8 × 8 × 4 = 256 màu) hoặc màu 16 bit (4 bit cho màu đỏ, xanh lá cây và xanh lam, cộng thêm 4 bit nữa . Có độ sâu màu với hơn tám bit trên mỗi kênh, nhưng vì mắt người chỉ có thể phân biệt được khoảng 10 triệu màu khác nhau nên những màu này thường không được sử dụng Nếu bạn đang sử dụng màn hình máy tính xách tay cũ hoặc rẻ tiền hoặc màn hình LCD để xem hình ảnh, nó có thể chỉ hỗ trợ màu 18-bit, có khả năng hiển thị 64 × 64 × 64 = 262.144 màu. Hình ảnh màu 24-bit sẽ được chuyển đổi theo một cách nào đó thành 18-bit và do đó, chất lượng màu bạn nhìn thấy sẽ không khớp với những gì thực sự có trong hình ảnh Chúng ta có thể kết hợp hệ tọa độ của mình với mô hình màu RGB 24 bit để hiểu khái niệm về những hình ảnh mà chúng ta sẽ làm việc với. Một hình ảnh là một mảng pixel hình chữ nhật, mỗi pixel có tọa độ riêng. Mỗi pixel trong ảnh là một điểm vuông của ánh sáng màu, trong đó màu được chỉ định bởi bộ ba RGB 24 bit. Một hình ảnh như vậy là một ví dụ về đồ họa raster định dạng hình ảnhMặc dù các hình ảnh mà chúng ta sẽ thao tác trong các chương trình của mình được khái niệm hóa dưới dạng các mảng hình chữ nhật của bộ ba RGB, nhưng chúng không nhất thiết phải được tạo, lưu trữ hoặc truyền ở định dạng đó. There are several image formats we might encounter, and we should know the basics of at least of few of them. Một số định dạng chúng tôi có thể gặp và phần mở rộng tệp của chúng được hiển thị trong bảng này FormatExtension Bitmap độc lập với thiết bị (BMP). bmpJoint Nhóm chuyên gia chụp ảnh (JPEG). jpg hoặc. jpeg Định dạng tệp hình ảnh được gắn thẻ (TIFF). tif hoặc. tiffBMPThe file format that comes closest to our preceding conceptualisation of images is the Device-Independent Bitmap, or BMP, file format. BMP files store raster graphics images as long sequences of binary-encoded numbers that specify the colour of each pixel in the image. Vì các tệp máy tính là cấu trúc một chiều nên các màu pixel được lưu trữ trên một hàng tại một thời điểm. Nghĩa là, hàng pixel đầu tiên (những pixel có tọa độ y 0) được lưu trữ trước, tiếp theo là hàng thứ hai (những pixel có tọa độ y 1), v.v. Tùy thuộc vào cách nó được tạo, hình ảnh BMP có thể có độ sâu màu 8-bit, 16-bit hoặc 24-bit 24-bit BMP images have a relatively simple file format, can be viewed and loaded across a wide variety of operating systems, and have high quality. Tuy nhiên, hình ảnh BMP không được nén, dẫn đến kích thước tệp rất lớn đối với bất kỳ độ phân giải hình ảnh hữu ích nào Ý tưởng nén hình ảnh rất quan trọng đối với chúng tôi vì hai lý do. đầu tiên, hình ảnh nén có kích thước tệp nhỏ hơn và do đó dễ dàng lưu trữ và truyền tải hơn; . Vì quá trình nén rất quan trọng đối với chúng tôi, nên chúng tôi nên đi một vòng ngắn và thảo luận về khái niệm này Nén hình ảnhTrước khi thảo luận về các định dạng bổ sung, việc làm quen với nén hình ảnh sẽ hữu ích. Hãy đi sâu vào chủ đề đó với một thử thách. Đối với thử thách này, bạn sẽ cần biết về bit/byte và cách chúng được sử dụng để thể hiện dung lượng lưu trữ của máy tính. Nếu bạn đã biết, bạn có thể bỏ qua thử thách bên dưới
Vì các tệp hình ảnh có thể rất lớn, nên có nhiều sơ đồ nén khác nhau để lưu (xấp xỉ) cùng một thông tin trong khi sử dụng ít dung lượng hơn. These compression techniques can be categorised as lossless or lossy Nén không mất dữ liệuTrong nén ảnh không mất dữ liệu, chúng tôi áp dụng một số thuật toán (i. e. , một quy trình được vi tính hóa) vào hình ảnh, dẫn đến một tệp nhỏ hơn đáng kể so với tệp BMP không nén tương đương sẽ là. Then, when we wish to load and view or process the image, our program reads the compressed file, and reverses the compression process, resulting in an image that is identical to the original. Không có gì bị mất trong quá trình này – do đó thuật ngữ “lossless. ” The general idea of lossless compression is to somehow detect long patterns of bytes in a file that are repeated over and over, and then assign a smaller bit pattern to represent the longer sample. Then, the compressed file is made up of the smaller patterns, rather than the larger ones, thus reducing the number of bytes required to save the file. Tệp nén cũng chứa một bảng các mẫu được thay thế và tệp gốc, vì vậy khi tệp được giải nén, nó có thể được tạo giống hệt với tệp gốc trước khi nén To provide you with a concrete example, consider the 71. 5 MB white BMP image discussed above. Khi đưa qua tiện ích nén zip trên Microsoft Windows, kết quả. zip file is only 72 KB in size. Đó là, các. zip version of the image is three orders of magnitude smaller than the original, and it can be decompressed into a file that is byte-for-byte the same as the original. Vì bản gốc rất lặp lại - chỉ đơn giản là bộ ba màu giống nhau được lặp lại 25.000.000 lần - nên thuật toán nén có thể giảm đáng kể kích thước của tệp Nếu bạn làm việc với. zip or . gz, bạn đang xử lý nén không mất dữ liệu Nén mất dữ liệuLossy compression takes the original image and discards some of the detail in it, resulting in a smaller file format. Mục tiêu là chỉ loại bỏ chi tiết mà ai đó đang xem hình ảnh sẽ không nhận thấy. Nhiều lược đồ nén mất dữ liệu có các mức nén có thể điều chỉnh để người tạo hình ảnh có thể chọn lượng chi tiết bị mất. The more detail that is sacrificed, the smaller the image files will be - but of course, the detail and richness of the image will be lower as well Điều này có thể tốt cho các hình ảnh được hiển thị trên các trang Web hoặc được in ra trên giấy ảnh 4 × 6, nhưng có thể hoặc không tốt cho công việc khoa học. Bạn sẽ phải quyết định xem việc giảm chất lượng hình ảnh và chi tiết có quan trọng đối với công việc của bạn hay không, so với việc tiết kiệm dung lượng do định dạng nén mất dữ liệu mang lại Điều quan trọng là phải hiểu rằng một khi hình ảnh được lưu ở định dạng nén mất dữ liệu, chi tiết bị mất chỉ là - bị mất. Tôi. e. , không giống như các định dạng không mất dữ liệu, với một hình ảnh được lưu ở định dạng mất dữ liệu, không có cách nào để tái tạo lại hình ảnh gốc theo cách từng byte JPEGJPEG images are perhaps the most commonly encountered digital images today. JPEG uses lossy compression, and the degree of compression can be tuned to your liking. It supports 24-bit colour depth, and since the format is so widely used, JPEG images can be viewed and manipulated easily on all computing platforms
Dưới đây là một ví dụ cho thấy cách nén JPEG có thể ảnh hưởng đến chất lượng hình ảnh. Consider this image of several maize seedlings (scaled down here from 11,339 × 11,336 pixels in order to fit the display) Bây giờ, chúng ta hãy phóng to và xem xét một phần nhỏ của nhãn trong bản gốc, đầu tiên ở định dạng không nén Đây là cùng một khu vực của hình ảnh, nhưng ở định dạng JPEG. We used a fairly aggressive compression parameter to make the JPEG, in order to illustrate the problems you might encounter with the format Hình ảnh JPEG rõ ràng có chất lượng kém hơn. Nó có ít biến đổi màu sắc hơn và pixelation đáng chú ý. Sự khác biệt về chất lượng thậm chí còn rõ rệt hơn khi kiểm tra biểu đồ màu cho từng hình ảnh. Biểu đồ cho biết tần suất mỗi giá trị màu xuất hiện trong một hình ảnh. Biểu đồ cho hình ảnh không nén (trái) và nén (phải) được hiển thị bên dưới Chúng ta sẽ học cách tạo các biểu đồ như thế này sau trong hội thảo. Sự khác biệt trong biểu đồ màu thậm chí còn rõ ràng hơn so với chính hình ảnh; Nếu cài đặt chất lượng cho ảnh JPEG của bạn cao (và do đó tỷ lệ nén tương đối thấp), ảnh có thể đủ chất lượng cho công việc của bạn. Tất cả phụ thuộc vào chất lượng bạn cần và bạn có những hạn chế nào đối với không gian lưu trữ hình ảnh. Một cân nhắc khác có thể là nơi lưu trữ hình ảnh. Ví dụ: nếu hình ảnh của bạn được lưu trữ trên đám mây và do đó phải được tải xuống hệ thống của bạn trước khi sử dụng chúng, bạn có thể muốn sử dụng định dạng hình ảnh nén để tăng tốc thời gian truyền tệp PNGHình ảnh PNG rất phù hợp để lưu trữ sơ đồ. It uses a lossless compression and is hence often used in web applications for non-photographic images. Định dạng này có thể lưu trữ dữ liệu RGB và độ chói đơn giản (kênh đơn, không có màu liên quan), trong số các dữ liệu khác. Dữ liệu hình ảnh được lưu trữ theo hàng và sau đó, trên mỗi hàng, một bộ lọc đơn giản, chẳng hạn như lấy sự khác biệt của các pixel liền kề, có thể được áp dụng để tăng khả năng nén của dữ liệu. Dữ liệu được lọc sau đó được nén trong bước tiếp theo và ghi ra đĩa TIFFHình ảnh TIFF phổ biến với các nhà xuất bản, nhà thiết kế đồ họa và nhiếp ảnh gia. TIFF images can be uncompressed, or compressed using either lossless or lossy compression schemes, depending on the settings used, and so TIFF images seem to have the benefits of both the BMP and JPEG formats. Nhược điểm chính của hình ảnh TIFF (ngoài kích thước của hình ảnh ở phiên bản không nén của định dạng) là chúng không thể đọc được bằng phần mềm xử lý và xem hình ảnh MetadataHình ảnh JPEG và TIFF hỗ trợ đưa siêu dữ liệu vào hình ảnh. Metadata is textual information that is contained within an image file. Metadata holds information about the image itself, such as when the image was captured, where it was captured, what type of camera was used and with what settings, etc. We normally don’t see this metadata when we view an image, but we can view it independently if we wish to (see Accessing Metadata, below). Điều quan trọng cần lưu ý ở giai đoạn này là bạn không thể dựa vào siêu dữ liệu của hình ảnh được bảo toàn hoàn toàn khi bạn sử dụng phần mềm để xử lý hình ảnh đó. Thư viện trình đọc/ghi hình ảnh mà chúng ta sử dụng trong suốt bài học này, 53, bao gồm siêu dữ liệu khi lưu hình ảnh mới nhưng có thể không giữ được một số trường siêu dữ liệu. Trong mọi trường hợp, hãy nhớ. nếu siêu dữ liệu quan trọng đối với bạn, hãy đề phòng để luôn bảo toàn các tệp gốc
Tổng hợp các định dạng ảnh sử dụng trong bài học nàyThe following table summarises the characteristics of the BMP, JPEG, and TIFF image formats Định dạng NénSiêu dữ liệuƯu điểmNhược điểmBMPNoneKhông cóCó thể xem phổ biến,Kích thước tệp lớn chất lượng cao JPEGLossyCó Có thể xem phổ biến,Chi tiết có thể bị mất kích thước tệp nhỏ hơn PNGLosslessCó Có thể xem phổ biến, tiêu chuẩn mở, kích thước tệp nhỏ hơnSiêu dữ liệu ít linh hoạt hơn TIFF, chỉ RGB
Làm việc với Skipage
Chúng tôi đã đề cập nhiều đến cách hình ảnh được thể hiện trong phần mềm máy tính. Trong tập này chúng ta sẽ tìm hiểu thêm một số phương pháp để truy cập và thay đổi hình ảnh kỹ thuật số Đọc, hiển thị và lưu hình ảnhImageio cung cấp các chức năng trực quan để đọc và ghi (lưu) hình ảnh. Tất cả các định dạng hình ảnh phổ biến, chẳng hạn như BMP, PNG, JPEG và TIFF đều được hỗ trợ, cùng với một số định dạng bí truyền khác. Kiểm tra tài liệu Định dạng được hỗ trợ để biết danh sách tất cả các định dạng. Matplotlib cung cấp một bộ sưu tập lớn các tiện ích vẽ đồ thị Hãy để chúng tôi kiểm tra một chương trình Python đơn giản để tải, hiển thị và lưu hình ảnh sang một định dạng khác. Here are the first few lines 22Đầu tiên, chúng tôi nhập mô-đun 89 của imageio ( 53) dưới dạng 91 để chúng tôi có thể đọc và ghi hình ảnh. Sau đó, chúng tôi sử dụng chức năng 62 để đọc một hình ảnh JPEG có tên ghế. jpg. Imageio đọc hình ảnh, chuyển đổi nó từ JPEG thành một mảng NumPy và trả về mảng đó; Tiếp theo, chúng tôi sẽ làm một cái gì đó với hình ảnh 23Once we have the image in the program, we first call 94 so that we will have a fresh figure with a set of axis independent from our previous calls. Tiếp theo, chúng tôi gọi 95 để hiển thị hình ảnhNow, we will save the image in another format 24Câu lệnh cuối cùng trong chương trình, 96, ghi hình ảnh vào tệp có tên 97 trong thư mục 74. The 99 function automatically determines the type of the file, based on the file extension we provide. Trong trường hợp này, tiện ích mở rộng 200 khiến hình ảnh được lưu dưới dạng TIFF
Thao tác pixelIn the Image Basics episode, we individually manipulated the colours of pixels by changing the numbers stored in the image’s NumPy array. Let’s apply the principles learned there along with some new principles to a real world example Giả sử chúng ta quan tâm đến hình ảnh cụm rễ ngô này. We want to be able to focus our program’s attention on the roots themselves, while ignoring the black background Vì hình ảnh được lưu trữ dưới dạng một mảng số, chúng ta có thể chỉ cần xem qua mảng để tìm các giá trị màu pixel nhỏ hơn một số giá trị ngưỡng. This process is called thresholding, and we will see more powerful methods to perform the thresholding task in the Thresholding episode. Tuy nhiên, ở đây, chúng ta sẽ xem xét một phương pháp NumPy đơn giản và tao nhã để tạo ngưỡng. Hãy để chúng tôi phát triển một chương trình chỉ giữ các giá trị màu pixel trong một hình ảnh có giá trị lớn hơn hoặc bằng 128. This will keep the pixels that are brighter than half of “full brightness”, i. e. , pixels that do not belong to the black background. Chúng tôi sẽ bắt đầu bằng cách đọc hình ảnh và hiển thị nó 27Now we can threshold the image and display the result 28Lệnh NumPy để bỏ qua tất cả các pixel cường độ thấp là 226. Mọi giá trị màu pixel trong toàn bộ mảng 3 chiều có giá trị nhỏ hơn 128 được đặt thành 0. Trong trường hợp này, kết quả là một hình ảnh trong đó chi tiết nền bên ngoài đã bị loại bỏChuyển đổi hình ảnh màu sang thang độ xámThường dễ dàng hơn khi làm việc với ảnh thang độ xám có một kênh thay vì ảnh màu có ba kênh. Skimage cung cấp chức năng 227 để đạt được điều này. This function adds up the three colour channels in a way that matches human colour perception, see the skimage documentation for details. Nó trả về một hình ảnh thang độ xám với các giá trị dấu phẩy động trong phạm vi từ 0 đến 1. Chúng ta có thể sử dụng hàm 218 để chuyển đổi nó trở lại kiểu dữ liệu ban đầu và phạm vi dữ liệu trở lại 0 đến 255. Lưu ý rằng thường tốt hơn nếu sử dụng các giá trị hình ảnh được biểu thị bằng các giá trị dấu phẩy động, bởi vì sử dụng số dấu phẩy động sẽ ổn định hơn về mặt số học
29We can also load colour images as grayscale directly by passing the argument 235 to 62 70
Truy cập thông qua cắt látNhư đã lưu ý trong bài học trước, hình ảnh lướt qua được lưu trữ dưới dạng mảng NumPy, vì vậy chúng ta có thể sử dụng tính năng cắt mảng để chọn các vùng hình chữ nhật của hình ảnh. Sau đó, chúng ta có thể lưu lựa chọn thành một hình ảnh mới, thay đổi các pixel trong hình ảnh, v.v. Điều quan trọng cần nhớ là các tọa độ được chỉ định theo thứ tự (ry, cx) và các giá trị màu được chỉ định theo thứ tự (r, g, b) khi thực hiện các thao tác này Hãy xem xét hình ảnh bảng trắng này và giả sử rằng chúng ta muốn tạo một hình ảnh con chỉ có phần ghi “lẻ + chẵn = lẻ”, cùng với hộp màu đỏ được vẽ xung quanh các từ Sử dụng cùng một kỹ thuật hiển thị mà chúng tôi đã sử dụng trong suốt khóa học này, chúng tôi có thể xác định tọa độ của các góc của khu vực mà chúng tôi muốn trích xuất bằng cách di chuột gần các điểm ưa thích và ghi lại tọa độ. Nếu chúng ta làm như vậy, chúng ta có thể giải quyết trên một khu vực hình chữ nhật có tọa độ phía trên bên trái là (135, 60) và tọa độ phía dưới bên phải là (480, 150), như thể hiện trong phiên bản hình ảnh bảng trắng này Lưu ý rằng tọa độ trong hình trước được chỉ định theo thứ tự (cx, ry). Bây giờ nếu toàn bộ hình ảnh bảng trắng của chúng tôi được lưu trữ dưới dạng hình ảnh lướt qua có tên là 93, chúng tôi có thể tạo một hình ảnh mới của vùng đã chọn bằng một câu lệnh như thế này 245Our array slicing specifies the range of y-coordinates or rows first, 246, and then the range of x-coordinates or columns, 247. Lưu ý rằng chúng tôi vượt quá giá trị tối đa trong mỗi thứ nguyên để toàn bộ khu vực mong muốn được chọn. The third part of the slice, 248, indicates that we want all three colour channels in our new imageA script to create the subimage would start by loading the image 74Sau đó, chúng tôi sử dụng cắt mảng để tạo một hình ảnh mới với khu vực đã chọn của chúng tôi và sau đó hiển thị hình ảnh mới 75We can also change the values in an image, as shown next 76Đầu tiên, chúng tôi lấy mẫu màu của một pixel tại một vị trí cụ thể của hình ảnh, lưu nó vào một biến có tên là 229, biến này tạo ra một mảng NumPy 1 × 1 × 3 với các giá trị màu xanh dương, xanh lá cây và đỏ cho pixel nằm ở ( . Sau đó, với lệnh 250, chúng tôi sửa đổi hình ảnh trong khu vực được chỉ định. Từ góc độ NumPy, điều này thay đổi tất cả các giá trị pixel trong phạm vi đó thành mảng được lưu trong biến 229. In this case, the command “erases” that area of the whiteboard, replacing the words with a beige colour, as shown in the final image produced by the program
Hoạt động Vẽ và Bitwise
The next series of episodes covers a basic toolkit of skimage operators. Với những công cụ này, chúng tôi sẽ có thể tạo các chương trình để thực hiện các phân tích hình ảnh đơn giản dựa trên những thay đổi về màu sắc hoặc hình dạng Drawing on imagesOften we wish to select only a portion of an image to analyze, and ignore the rest. Tạo một hình ảnh con hình chữ nhật bằng cách cắt, như chúng ta đã làm trong phần Biểu diễn hình ảnh trong phần lướt qua là một tùy chọn cho các trường hợp đơn giản. Một tùy chọn khác là tạo một hình ảnh đặc biệt khác, có cùng kích thước với hình gốc, với các điểm ảnh màu trắng cho biết khu vực cần lưu và các điểm ảnh màu đen ở mọi nơi khác. Một hình ảnh như vậy được gọi là mặt nạ. In preparing a mask, we sometimes need to be able to draw a shape - a circle or a rectangle, say - on a black image. Skipage cung cấp các công cụ để làm điều đó Xem xét hình ảnh này của cây ngô Now, suppose we want to analyze only the area of the image containing the roots themselves; we do not care to look at the kernels, or anything else about the plants. Further, we wish to exclude the frame of the container holding the seedlings as well. Di chuột qua hình ảnh, có thể cho chúng tôi biết tọa độ phía trên bên trái của vùng phụ mà chúng tôi quan tâm là (44, 357), trong khi tọa độ phía dưới bên phải là (720, 740). Các tọa độ này được hiển thị theo thứ tự (x, y) Một chương trình Python tạo mặt nạ để chỉ chọn vùng đó của hình ảnh sẽ bắt đầu bằng một đoạn mã quen thuộc để mở và hiển thị hình ảnh gốc 78Như trước đây, trước tiên chúng tôi nhập mô-đun con 89 của 56 ( 53). Chúng tôi cũng nhập thư viện NumPy mà chúng tôi cần để tạo hình ảnh mặt nạ ban đầu. Sau đó, chúng tôi nhập mô-đun con 39 của 32. Chúng tôi tải và hiển thị hình ảnh ban đầu giống như cách chúng tôi đã làm trước đâyNumPy cho phép lập chỉ mục các hình ảnh/mảng với các mảng “boolean” có cùng kích thước. Indexing with a boolean array is also called mask indexing. The “pixels” in such a mask array can only take two values. 265 hoặc 266. When indexing an image with such a mask, only pixel values at positions where the mask is 265 are accessed. Nhưng trước tiên, chúng ta cần tạo một mảng mặt nạ có cùng kích thước với hình ảnh. May mắn thay, thư viện NumPy cung cấp một hàm để tạo một mảng như vậy. Phần tiếp theo của mã cho thấy làm thế nào 79Đối số đầu tiên của hàm 268 là hình dạng của ảnh gốc, do đó mặt nạ của chúng ta sẽ có cùng kích thước với ảnh gốc. Notice, that we have only used the first two indices of our shape. We omitted the channel dimension. Lập chỉ mục với mặt nạ như vậy sẽ thay đổi đồng thời tất cả các giá trị kênh. Đối số thứ hai, 269, chỉ ra rằng các phần tử trong mảng phải là boolean - i. e. , values are either 265 or 266. Thus, even though we use 272 to create the mask, its pixel values are in fact not 273 but 265. You could check this, e. g. , by 275Next, we draw a filled, rectangle on the mask 90Here is what our constructed mask looks like. The parameters of the 276 function 277 and 278, are the coordinates of the upper-left ( 279) and lower-right ( 280) corners of a rectangle in (ry, cx) order. The function returns the rectangle as row ( 281) and column ( 282) coordinate arrays
Image modificationAll that remains is the task of modifying the image using our mask in such a way that the areas with 265 pixels in the mask are not shown in the image any more
Now we can write a Python program to use a mask to retain only the portions of our maize roots image that actually contains the seedling roots. We load the original image and create the mask in the same way as before 97Then, we use numpy indexing to remove the portions of the image, where the mask is 265 98Then, we display the masked image 99The resulting masked image should look like this
Creating Histograms
In this episode, we will learn how to use skimage functions to create and display histograms for images Introduction to HistogramsAs it pertains to images, a histogram is a graphical representation showing how frequently various colour values occur in the image. We saw in the Image Basics episode that we could use a histogram to visualise the differences in uncompressed and compressed image formats. If your project involves detecting colour changes between images, histograms will prove to be very useful, and histograms are also quite handy as a preparatory step before performing thresholding Grayscale HistogramsWe will start with grayscale images, and then move on to colour images. We will use this image of a plant seedling as an example. Here we load the image in grayscale instead of full colour, and display it 04Again, we use the 62 function to load our image. The first argument to 62 is the filename of the image. The second argument 235 defines the type and depth of a pixel in the image (e. g. , an 8-bit pixel has a range of 0-255). This argument is forwarded to the 721 backend, for which mode “L” means 8-bit pixels and single-channel (i. e. , grayscale). 721 is a Python imaging library; which backend is used by 62 may be specified (to use 721, you would pass this argument. 725); if unspecified, 62 determines the backend to use based on the image typeThen, we convert the grayscale image of integer dtype, with 0-255 range, into a floating-point one with 0-1 range, by calling the function 727. We will keep working with images in the value range 0 to 1 in this lessonWe now use the function 728 to compute the histogram of our image which, after all, is a NumPy array 05The parameter 729 determines the number of “bins” to use for the histogram. We pass in 730 because we want to see the pixel count for each of the 256 possible values in the grayscale imageThe parameter 731 is the range of values each of the pixels in the image can have. Here, we pass 0 and 1, which is the value range of our input image after transforming it to grayscaleThe first output of the 728 function is a one-dimensional NumPy array, with 256 rows and one column, representing the number of pixels with the intensity value corresponding to the index. I. e. , the first number in the array is the number of pixels found with intensity value 0, and the final number in the array is the number of pixels found with intensity value 255. The second output of 728 is an array with the bin edges and one column and 257 rows (one more than the histogram itself). There are no gaps between the bins, which means that the end of the first bin, is the start of the second and so on. For the last bin, the array also has to contain the stop, so it has one more element, than the histogramNext, we turn our attention to displaying the histogram, by taking advantage of the plotting facilities of the 734 library 06Chúng tôi tạo biểu đồ bằng 735, sau đó gắn nhãn hình và các trục tọa độ bằng các hàm 736, 737 và 738. The last step in the preparation of the figure is to set the limits on the values on the x-axis with the 739 function call
Finally, we create the histogram plot itself with 742. We use the left bin edges as x-positions for the histogram values by indexing the 743 array to ignore the last value (the right edge of the last bin). When we run the program on this image of a plant seedling, it produces this histogram
Colour HistogramsWe can also create histograms for full colour images, in addition to grayscale histograms. We have seen colour histograms before, in the Image Basics episode. A program to create colour histograms starts in a familiar way 08We read the original image, now in full colour, and display it Next, we create the histogram, by calling the 728 function three times, once for each of the channels. We obtain the individual channels, by slicing the image along the last axis. For example, we can obtain the red colour channel by calling 752 09We will draw the histogram line for each channel in a different colour, and so we create a tuple of the colours to use for the three lines with the 753line of code. Then, we limit the range of the x-axis with the 740 function callNext, we use the 755 control structure to iterate through the three channels, plotting an appropriately-coloured histogram line for each. This may be new Python syntax for you, so we will take a moment to discuss what is happening in the 755 statementThe Python built-in 757 function takes a list and returns an iterator of tuples, where the first element of the tuple is the index and the second element is the element of the list
In our colour histogram program, we are using a tuple, 761, as the 755 variable. The first time through the loop, the 763 variable takes the value 764, referring to the position of the red colour channel, and the 229 variable contains the string 766. The second time through the loop the values are the green channels index 273 and 768, and the third time they are the blue channel index 769 and 770Inside the 755 loop, our code looks much like it did for the grayscale example. We calculate the histogram for the current channel with the 772function call, and then add a histogram line of the correct colour to the plot with the 773function call. Note the use of our loop variables, 763 and 289Finally we label our axes and display the histogram, shown here
Blurring Images
In this episode, we will learn how to use skimage functions to blur images When processing an image, we are often interested in identifying objects represented within it so that we can perform some further analysis of these objects e. g. by counting them, measuring their sizes, etc. An important concept associated with the identification of objects in an image is that of edges. the lines that represent a transition from one group of similar pixels in the image to another different group. One example of an edge is the pixels that represent the boundaries of an object in an image, where the background of the image ends and the object begins When we blur an image, we make the colour transition from one side of an edge in the image to another smooth rather than sudden. The effect is to average out rapid changes in pixel intensity. A blur is a very common operation we need to perform before other tasks such as thresholding. There are several different blurring functions in the 787 module, so we will focus on just one here, the Gaussian blur
Gaussian blurConsider this image of a cat, in particular the area of the image outlined by the white square Now, zoom in on the area of the cat’s eye, as shown in the left-hand image below. When we apply a filter, we consider each pixel in the image, one at a time. In this example, the pixel we are currently working on is highlighted in red, as shown in the right-hand image When we apply a filter, we consider rectangular groups of pixels surrounding each pixel in the image, in turn. The kernel is another group of pixels (a separate matrix / small image), of the same dimensions as the rectangular group of pixels in the image, that moves along with the pixel being worked on by the filter. The width and height of the kernel must be an odd number, so that the pixel being worked on is always in its centre. In the example shown above, the kernel is square, with a dimension of seven pixels To apply the kernel to the current pixel, an average of the the colour values of the pixels surrounding it is calculated, weighted by the values in the kernel. In a Gaussian blur, the pixels nearest the centre of the kernel are given more weight than those far away from the centre. The rate at which this weight diminishes is determined by a Gaussian function, hence the name Gaussian blur A Gaussian function maps random variables into a normal distribution or “Bell Curve”. https. //en. wikipedia. org/wiki/Gaussian_function#/media/File. Normal_Distribution_PDF. svgThe shape of the function is described by a mean value μ, and a variance value σ². The mean determines the central point of the bell curve on the x axis, and the variance describes the spread of the curve In fact, when using Gaussian functions in Gaussian blurring, we use a 2D Gaussian function to account for X and Y dimensions, but the same rules apply. The mean μ is always 0, and represents the middle of the 2D kernel. Increasing values of σ² in either dimension increases the amount of blurring in that dimension https. //commons. wikimedia. org/wiki/File. Gaussian_2D. pngThe averaging is done on a channel-by-channel basis, and the average channel values become the new value for the pixel in the filtered image. Larger kernels have more values factored into the average, and this implies that a larger kernel will blur the image more than a smaller kernel To get an idea of how this works, consider this plot of the two-dimensional Gaussian function Imagine that plot laid over the kernel for the Gaussian blur filter. The height of the plot corresponds to the weight given to the underlying pixel in the kernel. I. e. , the pixels close to the centre become more important to the filtered pixel colour than the pixels close to the outer limits of the kernel. The shape of the Gaussian function is controlled via its standard deviation, or sigma. A large sigma value results in a flatter shape, while a smaller sigma value results in a more pronounced peak. The mathematics involved in the Gaussian blur filter are not quite that simple, but this explanation gives you the basic idea To illustrate the blur process, consider the blue channel colour values from the seven-by-seven region of the cat image above The filter is going to determine the new blue channel value for the centre pixel – the one that currently has the value 86. The filter calculates a weighted average of all the blue channel values in the kernel giving higher weight to the pixels near the centre of the kernel This weighted average, the sum of the multiplications, becomes the new value for the centre pixel (3, 3). The same process would be used to determine the green and red channel values, and then the kernel would be moved over to apply the filter to the next pixel in the image
This animation shows how the blur kernel moves along in the original image in order to calculate the colour channel values for the blurred image skimage has built-in functions to perform blurring for us, so we do not have to perform all of these mathematical operations ourselves. Let’s work through an example of blurring an image with the skimage Gaussian blur function First, we load the image, and display it 47Next, we apply the gaussian blur 48The first two parameters to 788 are the image to blur, 93, and a tuple defining the sigma to use in ry- and cx-direction, 790. The third parameter 791 gives the radius of the kernel in terms of sigmas. A Gaussian function is defined from -infinity to +infinity, but our kernel (which must have a finite, smaller size) can only approximate the real function. Therefore, we must choose a certain distance from the centre of the function where we stop this approximation, and set the final size of our kernel. In the above example, we set 791 to 3. 5, which means the kernel size will be 2 * sigma * 3. 5. For example, for a 793 of 1. 0 the resulting kernel size would be 7, while for a 793 of 2. 0 the kernel size would be 14. The default value for 791 in scikit-image is 4. 0The last parameter to 788 tells skimage to interpret our image, that has three dimensions, as a multichannel colour imageFinally, we display the blurred image 49
Other methods of blurringThe Gaussian blur is a way to apply a low-pass filter in skimage. It is often used to remove Gaussian (i. e. , random) noise from the image. For other kinds of noise, e. g. “salt and pepper” or “static” noise, a median filter is typically used. See the 787 documentation for a list of available filters
Thresholding
In this episode, we will learn how to use skimage functions to apply thresholding to an image. Thresholding is a type of image segmentation, where we change the pixels of an image to make the image easier to analyze. Trong ngưỡng, chúng tôi chuyển đổi một hình ảnh từ màu sắc hoặc thang độ xám thành một hình ảnh nhị phân, tôi. e. , one that is simply black and white. Most frequently, we use thresholding as a way to select areas of interest of an image, while ignoring the parts we are not concerned with. We have already done some simple thresholding, in the “Manipulating pixels” section of the Image Representation in skimage episode. In that case, we used a simple NumPy array manipulation to separate the pixels belonging to the root system of a plant from the black background. In this episode, we will learn how to use skimage functions to perform thresholding. Sau đó, chúng tôi sẽ sử dụng các mặt nạ được trả về bởi các chức năng này để chọn các phần của hình ảnh mà chúng tôi quan tâm Simple thresholdingConsider the image 904 with a series of crudely cut shapes set against a white background 51Now suppose we want to select only the shapes from the image. In other words, we want to leave the pixels belonging to the shapes “on,” while turning the rest of the pixels “off,” by setting their colour channel values to zeros. The skimage library has several different methods of thresholding. We will start with the simplest version, which involves an important step of human input. Cụ thể, trong ngưỡng đơn giản, mức cố định này, chúng tôi phải cung cấp giá trị ngưỡng 905The process works like this. First, we will load the original image, convert it to grayscale, and de-noise it as in the Blurring Images episode 52Next, we would like to apply the threshold 905 such that pixels with grayscale values on one side of 905 will be turned “on”, while pixels with grayscale values on the other side will be turned “off”. How might we do that? Remember that grayscale images contain pixel values in the range from 0 to 1, so we are looking for a threshold 905 in the closed range [0. 0, 1. 0]. We see in the image that the geometric shapes are “darker” than the white background but there is also some light gray noise on the background. One way to determine a “good” value for 905 is to look at the grayscale histogram of the image and try to identify what grayscale ranges correspond to the shapes in the image or the backgroundThe histogram for the shapes image shown above can be produced as in the Creating Histograms episode 53Vì hình ảnh có nền trắng nên hầu hết các pixel trong hình ảnh đều có màu trắng. This corresponds nicely to what we see in the histogram. there is a peak near the value of 1. 0. If we want to select the shapes and not the background, we want to turn off the white background pixels, while leaving the pixels for the shapes turned on. So, we should choose a value of 905 somewhere before the large peak and turn pixels above that value “off”. Hãy để chúng tôi chọn 911Để áp dụng ngưỡng 905, chúng ta có thể sử dụng toán tử so sánh numpy để tạo mặt nạ. Here, we want to turn “on” all pixels which have values smaller than the threshold, so we use the less operator 900 to compare the 914 to the threshold 905. Toán tử trả về một mặt nạ mà chúng ta chụp trong biến 916. Nó chỉ có một kênh và mỗi giá trị của nó là 0 hoặc 1. The binary mask created by the thresholding operation can be shown with 238, where the 266 entries are shown as black pixels (0-valued) and the 265 entries are shown as white pixels (1-valued) 54You can see that the areas where the shapes were in the original area are now white, while the rest of the mask image is black
We can now apply the 916 to the original coloured image as we have learned in the Drawing and Bitwise Operations episode. Những gì chúng ta còn lại chỉ là những hình dạng màu từ bản gốc 55
Ngưỡng tự độngNhược điểm của kỹ thuật tạo ngưỡng đơn giản là chúng ta phải đưa ra dự đoán có cơ sở về ngưỡng 905 bằng cách kiểm tra biểu đồ. Ngoài ra còn có các phương pháp ngưỡng tự động có thể tự động xác định ngưỡng cho chúng tôi. Một phương pháp như vậy là phương pháp của Otsu. Nó đặc biệt hữu ích cho các tình huống trong đó biểu đồ thang độ xám của ảnh có hai đỉnh tương ứng với nền và đối tượng quan tâm
Hãy xem xét hình ảnh 933 của hệ thống rễ ngô mà chúng ta đã thấy trước đây trong phần Biểu diễn bằng hình ảnh trong phần lướt qua 59Chúng tôi sử dụng độ mờ Gaussian với sigma là 1. 0 to denoise the root image. Chúng ta hãy xem biểu đồ thang độ xám của hình ảnh được khử nhiễu 60Biểu đồ có một đỉnh đáng kể xung quanh 0. 2, và một đỉnh thứ hai, nhỏ hơn rất gần 1. 0. Do đó, hình ảnh này là một ứng cử viên sáng giá để tạo ngưỡng bằng phương pháp của Otsu. Các chi tiết toán học về cách thức hoạt động của nó rất phức tạp (hãy xem tài liệu lướt qua nếu bạn quan tâm), nhưng kết quả là phương pháp của Otsu tìm thấy một giá trị ngưỡng giữa hai đỉnh của biểu đồ thang độ xám Hàm 934 có thể được sử dụng để xác định ngưỡng tự động thông qua phương pháp của Otsu. Sau đó, các toán tử so sánh numpy có thể được sử dụng để áp dụng nó như trước đây. Dưới đây là các lệnh Python để xác định ngưỡng 905 bằng phương pháp của Otsu 61 62Đối với hình ảnh gốc này và độ mờ Gaussian với sigma đã chọn là 1. 0, giá trị ngưỡng tính toán là 0. 42. No we can create a binary mask with the comparison operator 799. Như chúng ta đã thấy trước đây, các điểm ảnh trên giá trị ngưỡng sẽ được bật, những điểm ảnh dưới ngưỡng sẽ bị tắt 63Cuối cùng, chúng tôi sử dụng mặt nạ để chọn tiền cảnh 64Application. đo khối lượng rễBây giờ chúng ta hãy chuyển sang một ứng dụng trong đó chúng ta có thể áp dụng phân ngưỡng và các kỹ thuật khác mà chúng ta đã học được cho đến thời điểm này. Consider these four maize root system images, which you can find in the files 937, 938, 939, and 940Giả sử chúng ta quan tâm đến số lượng vật liệu thực vật trong mỗi hình ảnh và đặc biệt là số lượng đó thay đổi như thế nào từ hình ảnh này sang hình ảnh khác. Có lẽ những hình ảnh đại diện cho sự phát triển của cây theo thời gian, hoặc có lẽ những hình ảnh cho thấy bốn giống ngô khác nhau ở cùng một giai đoạn phát triển của chúng. Câu hỏi mà chúng tôi muốn trả lời là "khối lượng gốc trong mỗi hình ảnh là bao nhiêu?" Trước tiên, chúng tôi sẽ xây dựng một chương trình Python để đo giá trị này cho một hình ảnh. Chiến lược của chúng tôi sẽ là thế này
Mục đích của chúng tôi là thực hiện các bước này và tạo ra kết quả số - thước đo khối lượng rễ trong ảnh - mà không cần sự can thiệp của con người. Implementing the steps within a Python function will enable us to call this function for different images Here is a Python function that implements this root-mass-measuring strategy. Vì chức năng nhằm tạo ra đầu ra số mà không có sự tương tác của con người, nên nó không hiển thị bất kỳ hình ảnh nào. Hầu như tất cả các lệnh đều quen thuộc và trên thực tế, nó có vẻ đơn giản hơn mã mà chúng tôi đã làm việc cho đến nay, bởi vì chúng tôi không hiển thị bất kỳ hình ảnh nào 65Chức năng bắt đầu bằng việc đọc ảnh gốc từ tệp 941. Chúng tôi sử dụng 62 với đối số tùy chọn 235 để tự động chuyển đổi nó thành thang độ xám. Tiếp theo, hình ảnh thang độ xám được làm mờ bằng bộ lọc Gaussian với giá trị 793 được truyền cho hàm. Sau đó, chúng tôi xác định ngưỡng 905 bằng phương pháp của Otsu và tạo mặt nạ nhị phân giống như chúng tôi đã làm trong phần trước. Đến thời điểm này, mọi thứ chắc đã quen thuộcPhần cuối cùng của chức năng xác định tỷ lệ khối lượng gốc trong hình ảnh. Nhớ lại rằng trong 916, mỗi pixel có giá trị bằng 0 (đen/nền) hoặc một (trắng/nền trước). Chúng tôi muốn đếm số pixel trắng, có thể được thực hiện bằng cách gọi hàm numpy 947. Sau đó, chúng tôi xác định chiều rộng và chiều cao của hình ảnh bằng cách sử dụng các phần tử của 948 (nghĩa là kích thước của mảng numpy lưu trữ hình ảnh). Cuối cùng, tỷ lệ mật độ được tính bằng cách chia số pixel trắng cho tổng số pixel 949 trong ảnh. Hàm trả về mật độ gốc của hình ảnhChúng ta có thể gọi hàm này với bất kỳ tên tệp nào và cung cấp giá trị sigma để làm mờ. Nếu không có giá trị sigma nào được cung cấp, giá trị mặc định 1. 0 sẽ được sử dụng. Ví dụ: đối với tệp 937 và giá trị sigma là 1. 5, chúng ta sẽ gọi hàm như thế này 66 67Bây giờ chúng ta có thể sử dụng chức năng để xử lý chuỗi bốn hình ảnh được hiển thị ở trên. Trong một tình huống khoa học trong thế giới thực, có thể có hàng chục, hàng trăm hoặc thậm chí hàng nghìn hình ảnh cần xử lý. Để tiết kiệm cho chúng tôi sự tẻ nhạt khi gọi hàm cho từng hình ảnh bằng tay, chúng tôi có thể viết một vòng lặp xử lý tất cả các tệp tự động. Khối mã sau đây giả định rằng các tệp được đặt trong cùng một thư mục và tất cả các tên tệp đều bắt đầu bằng tiền tố dùng thử và kết thúc bằng tiền tố. hậu tố jpg 68 69
Phân tích thành phần được kết nối
Các đối tượngTrong phần Ngưỡng, chúng ta đã đề cập đến việc chia một hình ảnh thành các pixel nền trước và nền sau. Trong hình ảnh ví dụ về hình dạng, chúng tôi coi các hình dạng có màu là đối tượng tiền cảnh trên nền trắng In thresholding we went from the original image to this version Here, we created a mask that only highlights the parts of the image that we find interesting, the objects. Tất cả các đối tượng có giá trị pixel là ________ 2265 trong khi pixel nền là ________ 2266 Bằng cách nhìn vào hình ảnh mặt nạ, người ta có thể đếm các đối tượng có trong hình ảnh (7). Nhưng làm cách nào chúng tôi thực sự làm được điều đó, làm cách nào chúng tôi quyết định được cụm pixel nào tạo thành một đối tượng? Vùng lân cận pixelĐể quyết định pixel nào thuộc cùng một đối tượng, người ta có thể khai thác vùng lân cận của chúng. pixel trực tiếp cạnh nhau và thuộc về lớp tiền cảnh có thể được coi là thuộc về cùng một đối tượng Hãy thảo luận chi tiết hơn về khái niệm vùng lân cận pixel. Xem xét mặt nạ “hình ảnh” sau đây với 8 hàng và 8 cột. Với mục đích minh họa, chữ số 764 được sử dụng để biểu thị pixel nền và chữ cái 963 được sử dụng để biểu thị pixel đối tượng nền trước) 74Các pixel được tổ chức trong một lưới hình chữ nhật. Để hiểu các vùng lân cận pixel, chúng tôi sẽ giới thiệu khái niệm "nhảy" giữa các pixel. Các bước nhảy tuân theo hai quy tắc. Nguyên tắc đầu tiên là chỉ được phép nhảy một lần dọc theo cột hoặc hàng. Nhảy chéo không được phép. Vì vậy, từ một pixel trung tâm, được biểu thị bằng 964, chỉ các pixel được biểu thị bằng 273 mới có thể truy cập được 75Các pixel trên đường chéo (từ 964) không thể truy cập được bằng một lần nhảy, được biểu thị bằng 967. Các pixel có thể truy cập bằng một bước nhảy duy nhất tạo thành vùng lân cận 1 bước nhảyQuy tắc thứ hai quy định rằng trong một chuỗi nhảy, người ta chỉ được nhảy theo hướng hàng và cột một lần -> chúng phải trực giao. Một ví dụ về chuỗi các bước nhảy trực giao được hiển thị bên dưới. Bắt đầu từ 964, bước nhảy đầu tiên đi dọc theo hàng bên phải. Bước nhảy thứ hai sau đó đi dọc theo hướng cột lên. Sau đó, trình tự không thể tiếp tục vì một bước nhảy đã được thực hiện theo cả hướng hàng và cột 76Tất cả các pixel có thể truy cập bằng một hoặc hai bước nhảy từ vùng lân cận 2 bước nhảy. Lưới bên dưới minh họa các pixel có thể truy cập từ pixel trung tâm 964 bằng một lần nhảy, được đánh dấu bằng 273 và các pixel có thể truy cập bằng 2 lần nhảy với một 769 77We want to revisit our example image mask from above and apply the two different neighborhood rules. Với một kết nối nhảy duy nhất cho mỗi pixel, chúng tôi nhận được hai đối tượng kết quả, được đánh dấu trong ảnh bằng 972 và 973 78Trong phiên bản 1 lần nhảy, chỉ những pixel có hàng xóm trực tiếp dọc theo hàng hoặc cột mới được coi là đã kết nối. Các kết nối chéo không được bao gồm trong vùng lân cận 1 bước nhảy. Tuy nhiên, với hai bước nhảy, chúng tôi chỉ nhận được một đối tượng duy nhất 972 vì các pixel cũng được coi là được kết nối dọc theo các đường chéo 79
Phân tích thành phần được kết nốiĐể tìm các đối tượng trong một hình ảnh, chúng tôi muốn sử dụng một thao tác được gọi là Phân tích thành phần được kết nối (CCA). Thao tác này lấy một hình ảnh nhị phân làm đầu vào. Thông thường, giá trị 266 trong hình ảnh này được liên kết với pixel nền và giá trị 265 biểu thị pixel tiền cảnh hoặc đối tượng. Một hình ảnh như vậy có thể được tạo ra, e. g. , với ngưỡng. Đưa ra một hình ảnh ngưỡng, phân tích thành phần được kết nối tạo ra một hình ảnh được dán nhãn mới với các giá trị pixel nguyên. Các pixel có cùng giá trị, thuộc về cùng một đối tượng. Skimage cung cấp phân tích thành phần được kết nối trong chức năng 977. Hãy để chúng tôi thêm chức năng này vào các bước đã quen thuộc để tạo ngưỡng cho một hình ảnh. Ở đây chúng tôi định nghĩa một hàm Python có thể tái sử dụng 978 01Lưu ý nhập mới của 979 để sử dụng chức năng 980 thực hiện CCA. Bốn dòng mã đầu tiên quen thuộc từ tập ThresholdingSau đó, chúng tôi gọi hàm 980. Hàm này có một đối số vị trí trong đó chúng tôi vượt qua 916, i. e. , hình ảnh nhị phân để làm việc trên. Với đối số tùy chọn 983, chúng tôi chỉ định vùng lân cận theo đơn vị bước nhảy trực giao. Ví dụ: bằng cách đặt 984, chúng tôi sẽ xem xét vùng lân cận 2 bước nhảy được giới thiệu ở trên. Hàm trả về một 985 trong đó mỗi pixel có một giá trị duy nhất tương ứng với đối tượng mà nó thuộc về. Ngoài ra, chúng tôi chuyển tham số tùy chọn 986 để trả về chỉ số nhãn tối đa là 987
Chúng ta có thể gọi hàm trên 978 và hiển thị hình ảnh được gắn nhãn như vậy 04
Ta có thể dùng hàm 011 để convert màu trong ảnh (nhớ lại ta đã dùng hàm 227 để convert sang grayscale). Với 011, tất cả các đối tượng được tô màu theo danh sách màu có thể tùy chỉnh. Chúng ta có thể sử dụng các lệnh sau để chuyển đổi và hiển thị hình ảnh 07
Bạn có thể thắc mắc tại sao phân tích thành phần được kết nối với 022 và 023 tìm thấy 11 đối tượng, trong khi chúng tôi mong đợi chỉ có 7 đối tượng. Bốn đối tượng bổ sung ở đâu? Đối với chúng tôi, rõ ràng những điểm nhỏ này là đồ tạo tác chứ không phải đối tượng mà chúng tôi quan tâm. Nhưng làm thế nào chúng ta có thể nói với máy tính? . Trong một số trường hợp, tiếng ồn xung quanh được coi là một đối tượng. Và với các tham số khác, một số đối tượng nền trước bị vỡ hoặc biến mất hoàn toàn. Do đó, chúng ta cần các tiêu chí khác để mô tả các thuộc tính mong muốn của các đối tượng được tìm thấy. Hình thái học - Mô tả đặc điểm đối tượng bằng các con sốHình thái học liên quan đến phân tích định lượng của các đối tượng và xem xét các thuộc tính như kích thước và hình dạng. Đối với ví dụ về hình ảnh có hình dạng, trực giác của chúng ta cho chúng ta biết rằng các đối tượng phải có kích thước hoặc diện tích nhất định. Vì vậy, chúng ta có thể sử dụng diện tích tối thiểu làm tiêu chí khi phát hiện một đối tượng. Để áp dụng một tiêu chí như vậy, chúng ta cần một cách để tính diện tích của các đối tượng được tìm thấy bởi các thành phần được kết nối. Nhớ lại cách chúng ta xác định khối lượng gốc trong phần Ngưỡng bằng cách đếm các pixel trong mặt nạ nhị phân. Nhưng ở đây chúng tôi muốn tính diện tích của một số đối tượng trong hình ảnh được dán nhãn. Thư viện skipage cung cấp hàm 028 để đo các thuộc tính của vùng được dán nhãn. Nó trả về một danh sách 029 mô tả từng vùng được kết nối trong ảnh. Các thuộc tính có thể được truy cập bằng cách sử dụng các thuộc tính của kiểu dữ liệu 029. Ở đây chúng ta sẽ sử dụng các thuộc tính 031 và 032. Bạn có thể khám phá tài liệu về lướt web để tìm hiểu về các thuộc tính khác có sẵnChúng ta có thể nhận được một danh sách các khu vực của các đối tượng được dán nhãn như sau 11Điều này sẽ tạo ra đầu ra 12
Thử thách đỉnh cao
Trong tập này, chúng tôi sẽ đưa ra thử thách cuối cùng để bạn thử sức, dựa trên tất cả các kỹ năng bạn đã đạt được cho đến nay. Thử thách này sẽ liên quan đến hình dạng của đối tượng trong ảnh (hình thái học) hình thái học. Đếm khuẩn lạc vi khuẩnNhư đã đề cập trong phần giới thiệu hội thảo, thách thức hình thái học của bạn là xác định có bao nhiêu khuẩn lạc trong mỗi hình ảnh này Các tệp hình ảnh có thể được tìm thấy tại 082, 083 và 084
|