10

I'm new with raster in QGIS. I have a three-band (RGB) georeferenced raster similar to this: (Reference)

enter image description here

And I would like to extract the pixels with similar color like in the following image by given a tolerance value as in Photoshop. In Photoshop, you can change color range to be selected using tolerance value. Two different results depending on the value 32 and 70 are seen in the two images below. (In both images, the darker blue area was clicked by "The Magic Wand Tool")

enter image description here

enter image description here

I was only able to find the following two posts that are most relevant to this topic. But they don't meet my need.

  1. Extracting GeoTIFF colours and adding to equal geometry shapefile
  2. Extracting shapefile attributes from raster colors using PyQGIS?

So, how can I extract the pixels using a color tolerance, as in Photoshop? It doesn't have to be a tolerance value, my ultimate goal is to extract pixels of similar color, but, somehow, I need to be able to set the similarity.

6
  • Excuse me if I mistook your goal. Are you looking for a tool like Gimp Selection Feature tool?
    – Kazuhito
    Nov 27, 2021 at 0:02
  • @Kazuhito No, not selection. But extracting similar colored pixels as a new raster/layer. I couldn't activate the plugin in any way. Though, making selection in GIMP, creating a polygon from the selection and clipping raster by the polygon sounds promising. Nov 27, 2021 at 6:55
  • I use for similar tasks a workflow where I do the extraction in image processing software (like Photoshop) because there you have the most soffisticated tools for that. Then import to (Q)GIS. If you have a worldfile, georeference should stay intact.
    – Babel
    Nov 29, 2021 at 18:36
  • @Babel Nice idea. I can do it in my computer (I have Photoshop). But, Photoshop (or another one) may not be available. Nov 29, 2021 at 18:55
  • Or an OpenSource solution like GIMP. But let's hope for a better solution using QGIS only
    – Babel
    Nov 29, 2021 at 19:29

2 Answers 2

4

There is the Magic Wand plugin in QGIS that works similar to the magic wand tool known from graphic software. Install the plugin, then simply click on the map canvas and the plugin creates a polygon layer with the selection.

You could use this polygon to rasterize and use the Raster Calculator to mask the colors in the initial raster - or simply use the polygon layer for that.

You can change the Accuracy (Fast to Precise) and Color Threshold (Ambiguous to Strict).

One single click on the Ottoman Empire was enough to create Polygon styled in red hachures: C:\Users\DU\Desktop\temp_new\320.tif

0
4

Extract pixels with similar color (tolerance) in QGIS

There is a way to do this in QGIS using raster calculator.

Remark: the image used here for demonstration purpose is really a "difficult" one: what should be one single color in fact consists of a lot of different shades that are difficult to perfectly isolate, even using a professional image processing image. Keep this in mind - other images, as the one you posted, seem to be easier.

Manual version: the basic principle

  1. Sample the RGB values of the raster with the Identify Features tool and for each band get the min/max values of the color you want to mask.

  2. Use raster calculator with an expression like this and replace the pixel values for each band with those from above:

    "raster@1" > 175 and "raster@1" < 210 and 
    "raster@2" > 175 and "raster@2" < 195 and
    "raster@3" > 70 and "raster@3" < 135
    

Result for masking the Ottoman Empire with the values from above: enter image description here

Semi-automatic version: calculate min/max range and create raster calculator expression

For a partial automatization of this solution, proceed as follows:

  1. Create a point layer and add a few points on spots that cover the raster color you want to mask. The points are intended to sample the RGB color values of the raster.
  2. Get the raster-value of all three RGB bands using QGIS expressions with raster_value() (similar to this solution).
  3. Then aggregate these values for all points to get min/max values for each band. An even more sophisticated solution could include adding a further tolerance, like subtracting/adding 10% of the total range from/to the min/max values.
  4. Based on that automatically create the expression used for the raster calculator.

Use this expression on the point layer to generate an output string that you can copy and introduce without any changes to the raster calculator:

regexp_replace( 
    array_to_string (
        array_foreach (
            array (1,2,3),
            '"raster@'  ||  @element  || '" >'  || 
            eval (' array_min (array_agg (raster_value (''raster'','  || @element  || ', $geometry)))' ) || 
            ' and "raster@'  ||  @element  || '" < '  || 
            eval ('array_max (array_agg (raster_value (''raster'','  || @element  || ', $geometry)))')  || ' and'
        )
    ),
    '(,)|(and$)',' ')

The output of this expression looks like this for the example I used in the next screenshot: use this in the raster calculator:

"raster@1" >181 and "raster@1" < 217 and "raster@2" >178 and "raster@2" < 201 and "raster@3" >64 and "raster@3" < 114  

Example used with (on the left) in yellow the points used to sample the colors to mask; on the right: the output from raster calculator used with the expression generated: enter image description here

Further possibilities: PyQGIS

I suppose that this second, semi-automatic version could be further automatized using PyQGIS, but that is your domain of expertise. It would be great to create and share a skript based on the second, semi-automatic solution like: click once (or twice or more times) on the picture, then the pixel values are internally calculated (maybe even with an option to define an additional tolerance range) and an output as on the screenshots is created. Or even several outputs with different tolerance ranges to select the best one. I guess a preview or pixel selection (like in image processing) is not possible in QGIS, but I might be wrong.

Workflow with Image processing software

The above solution works more or less, but can be cumbersome and does not give you the type of intuitive work that you have with image processing software. Therefore, I use a much easier workflow:

  1. Export the image from QGIS and create a world file.

    Before further proceeding maybe save a copy of the image and worldfile.

  2. Open the picture in an image processing software like GIMP, Affinity Photo or Photoshop and do the color selection/replacement there. Save the image.

  3. Reopen the image in QGIS. If the corrected image and the world file are in the same folder and have the same filename (and you don't change size/resolution of the image), the georeference still works.

I suppose this kind of selecting colors with a tolerance is not a core functionality of GIS. However, it is a core functionality of image processing. Because of that, it is better and easier done there. It is much faster and gives better results.

The following result was achieved with two clicks using Sampled colour pixel selections in Affinity Photo - not worse than the one above, but much faster:

enter image description here

2
  • Thank you for your intensive effort. But when working with raster data, I prefer not to mess with vector data and vice versa. I think the same about PyQGIS. But I haven't worked on raster data using PyQGIS so far. Dec 24, 2021 at 12:32
  • Maybe instead of creating points, with PyQGIS its possible to just click on the image to get the RGB values?
    – Babel
    Dec 24, 2021 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.