igor_r Posted October 29, 2023 Report Posted October 29, 2023 Hello everyone, In this article I will demonstrate how to create a crawler script for detecting grayscale images. It might be useful to know if an image is grayscale for various reasons. One of them is that such images are often scanned or faxed documents. Therefore, one may choose to OCR grayscale images only. Preparations We will be using Python and OpenCV library. Before we begin, we need to add OpenCV library to the Python bundled in Intella. To do that, open command line prompt as Administrator. Change the directory to c:\Program Files\Vound\Intella 2.6.1\python and execute this command: > cd c:\Program Files\Vound\Intella 2.6.1\python > .\python.exe -m pip install opencv-python-headless Collecting opencv-python-headless Downloading opencv_python_headless-4.8.1.78-cp37-abi3-win_amd64.whl (38.0 MB) Collecting numpy>=1.21.2 Downloading numpy-1.26.1-cp310-cp310-win_amd64.whl (15.8 MB) Successfully installed numpy-1.26.1 opencv-python-headless-4.8.1.78 If you see the message "Successfully installed" that means it worked fine. Now Intella can use OpenCV. Testing the algorithm Before we begin, let's create a simple app that we can use for testing the algorithm. The idea is very simple: First, we load the image file using OpenCV library. Then, we convert the color space from RGB to HSV (hue, saturation and value). That allows us to access the saturation part of each pixel. The pixels with low saturation appear as gray. Split the image data into three different arrays corresponding for H, S and V Use the maximum value of the S array to detect the maximum saturation of the image. If the max saturation is lower than the threshold that means this is a grayscale image. The following diagram demonstrates how colors with low saturation look like (the middle of the cylinder): Here is the code that we can use: import sys, cv2 img_file = sys.argv[1] img = cv2.imread(img_file) hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) h, s, v = cv2.split(hsv) print('Max saturation: ' + str(s.max())) Copy this text to a text file and save it as "detect_grayscale_test.py" (or download from here). Let's try to run it to analyze the picture of London from Wikipedia. Download the picture and save it to a folder on disk. Let's use the command line prompt from the previous step. Run this command: > .\python.exe C:\temp\detect_grayscale.py C:\temp\London_Skyline_Color.jpg Max saturation: 255 The script returned the maximum value which is 255. That means that the picture is not grayscale which is correct. Now, download this grayscale sample from Wikipedia: Grayscale_8bits_palette_sample_image.png. And run the app again: .\ python.exe C:\temp\detect_grayscale.py C:\temp\Grayscale_8bits_palette_sample_image.png Max saturation: 0 The result is zero now which is again correct. That indicates a grayscale image. Creating a crawler script Now let's create a crawler script. First, let's transform our test code into a function, so that we can use it in the script. The function will return an integer value that represents the max saturation of the image: def get_max_saturation(img_file): img = cv2.imread(img_file) hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) h, s, v = cv2.split(hsv) return s.max() In order to create a crawler script we need to define a class that implements ScriptService.Iface and two functions itemFound and itemProcessed. See detailed description of crawler scripts work on the GitHub page: intella-crawler-scripts. Let's just use this empty crawler script as a starting point: class ScriptHandler(ScriptService.Iface): def itemFound(self, item): return FoundItemResult(action=Action.Include) def itemProcessed(self, item): return ProcessedItemResult(action=Action.Include) For our script we can use either function. Both have access to the item type and binary content. That is all we need. Let's use itemProcessed. We can use item.mediaType property to determine if the item is an image. All image types start with "image/" prefix (examples: image/jpeg, image/png and so on). Then we calculate the max saturation using the function that we have just created and store the value in a custom column "Color Saturation". This will help to check how the algorithm works. If the max saturation is less than a threshold, we tag this item as "Grayscale". The threshold in this example is set to 20, but it could be adjusted if needed. def itemProcessed(self, item): custom_columns = [] tags = set() if item.binaryFile is not None and item.mediaType is not None and item.mediaType.startswith("image/"): max_saturation = get_max_saturation(item.binaryFile) sat_column = CustomColumn("Color Saturation", CustomColumnType.Integer, CustomColumnValue(intValue=max_saturation)) custom_columns = [sat_column] if max_saturation <= 20: tags.add("Color Detection/Grayscale") else: tags.add("Color Detection/Color") return ProcessedItemResult(action=Action.Include, customColumns=custom_columns, tags=tags) The complete script can be downloaded from here: detect_grayscale.py Now let's test the script. Launch Intella and create a new case, add the folder with two images that we have just downloaded. Add the crawler script on the Options page: Click "Validate" to validate the script. Index the source. When the indexing is finished, we can see that the script worked correctly. One image was detected as grayscale and the other one was detected as colored. We can see the new custom column and tags: 1 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.