How to I extract objects? [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
This post was edited and submitted for review last year and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I want to split images like this in a way that every symbols gets splits up vertically kind of like this input image:
![input image][1]
to this:
![here][2]
The problem is each symbol might have different width so I can't really fix the splitting points like we do in array splitting. If all objects had same width then I could segment the image base on width. In this scenario, what logic I should use to extract these connected objects?

First load the img from the url
import numpy as np
import urllib.request
from PIL import Image
from matplotlib import pyplot as plt
urllib.request.urlretrieve(
'https://i.stack.imgur.com/GRHzg.png',
"img.png")
img = Image.open("img.png")
img.show()
Then consider the black part as "filled" and convert in numpy array
arr = (np.array(img)[:,:,:-1].sum(axis=-1)==0)
If we sum the rows values for each column we can have a simple sum of how much pixel are filled in each column:
plt.subplot(211)
plt.imshow(arr, aspect="auto")
plt.subplot(212)
plt.plot(arr.sum(axis=0))
plt.xlim(0,arr.shape[1])
finally if we compute the differential of this sum over the columns we can obtain the following result:
plt.subplot(211)
plt.imshow(arr, aspect="auto")
plt.subplot(212)
plt.plot(np.diff(arr.sum(axis=0)))
plt.xlim(0,arr.shape[1])
At this point you can simply chose a threshold and cut the image:
threshold = 25
cut = np.abs(np.diff(arr.sum(axis=0)))>threshold
x_lines = np.arange(len(cut))[cut]
plt.imshow(arr, aspect="auto")
plt.vlines(x_lines, 0, arr.shape[0], color="r")
This is my solution and it works fine, but it is sensitive to the chosen threshold and to the columns gradient. I hope it is useful.

Related

I want to plot a heatmap on a png [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 days ago.
Improve this question
I have a dataset of x and y coordinates of eye gaze data with fixation duration.
I want to plot a heatmap on a png image and the output will be like in the picture or in the link
How do I plot it in Python
Let's assume that this is the database below
we have x , y and time [900.399, 980.142, 0.78] ,, so the longest time represents high temperature and the shortest time represents low temperature
x and y represent the coordinates of the eye focus on the image because the image = width and height x and y
data = [ [900.399, 980.142, 0.78], [922.252, 880.885, 0.68], [724.311, 780.543, 0.58], [523.195, 582.994, 0.46], [623.431, 680.427, 0.76], [926.363, 881.791, 1.81], [722.942, 783.257, 0.75], [223.751, 279.995, 0.16], [723.215, 781.004, 0.64], [724.541, 779.889, 0.55] ]
and let's also assume that this is the width and height image that I want to plot on it = [1920, 1080]
Can someone help me designing a method in python to generate heatmap.
https://i.insider.com/53ce61e16bb3f7dd693ffa82?width=1000&format=jpeg&auto=webp

How to arrange objects in rows and columns and export in .svg [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I'm new to Python, and I am trying to access Google's QuickDraw Database and arrange an amount of images (vector lines) as per the user's input of columns and rows, then export in .svg file format. So far, I have only managed to save each image as .gif and display it. How can I arrange them in a say 3x3 grid and in .svg format?
Here is the code I've got so far:
from PIL import Image, ImageDraw
from quickdraw.data import QuickDrawData
rows = int(input("How many rows do you want? "))
columns = int(input("How many columns do you want? "))
rows_columns = rows * columns
name_var = 0
for image in range(0,rows_columns):
qd = QuickDrawData()
duck = qd.get_drawing("duck")
duck_image = Image.new("RGB", (255,255), color = (255,255,255))
duck_drawing = ImageDraw.Draw(duck_image)
for stroke in duck.strokes:
for coordinate in range(len(stroke)-1):
x1 = stroke[coordinate][0]
y1 = stroke[coordinate][1]
x2 = stroke[coordinate+1][0]
y2 = stroke[coordinate+1][1]
duck_drawing.line((x1,y1,x2,y2), fill=(0,0,0), width=2)
duck_image.show()
name_var += 1
duck.image.save(f"my_duck{name_var}.gif")
This is ideally what the outcome should look like and in .svg file format.
You will need a python library that can output SVG files.
Unfortunately I don't have the time to provided a detailed answer with a code snippet that just runs but hopefully I can provide some directions.
There are mulitple python modules to write SVG files: svgwrite is one of them (docs, examples).
Based on the example snippet:
import svgwrite
dwg = svgwrite.Drawing('test.svg', profile='tiny')
dwg.add(dwg.line((0, 0), (10, 0), stroke=svgwrite.rgb(10, 10, 16, '%')))
dwg.add(dwg.text('Test', insert=(0, 0.2), fill='red'))
dwg.save()
you should be able to do something like:
from PIL import Image, ImageDraw
from quickdraw.data import QuickDrawData
import svgwrite
dwg = svgwrite.Drawing('test.svg', profile='tiny')
rows = int(input("How many rows do you want? "))
columns = int(input("How many columns do you want? "))
rows_columns = rows * columns
name_var = 0
for image in range(0,rows_columns):
qd = QuickDrawData()
duck = qd.get_drawing("duck")
duck_image = Image.new("RGB", (255,255), color = (255,255,255))
duck_drawing = ImageDraw.Draw(duck_image)
for stroke in duck.strokes:
for coordinate in range(len(stroke)-1):
x1 = stroke[coordinate][0]
y1 = stroke[coordinate][1]
x2 = stroke[coordinate+1][0]
y2 = stroke[coordinate+1][1]
duck_drawing.line((x1,y1,x2,y2), fill=(0,0,0), width=2)
# you many need to offset dwg.line using row/col grid index and drawing size
dwg.add(dwg.line((x1, y1), (x2, y2), stroke=svgwrite.rgb(10, 10, 16, '%')))
duck_image.show()
name_var += 1
duck.image.save(f"my_duck{name_var}.gif")
# save svg of all ducks (grid)
dwg.save()
Bare in mind the code above isn't tested, but hopefull it illustrates the point. If you're new to the module I recommend a step by step approach:
a basic test script writing a basic svg (e.g. example snippet): ensure the module is installed correctly and works
a basic script using quickdraw and svgwrite to draw a single duck
a script that draws a grid of ducks
The idea is if any steps fail, it will be easier to debug/fix in isolation.
I suspect you might also need to work out the dimensions/bounding box of each duck and scale/align to a same sized rectangle for the grid then offset each line coordinates. In theory you might be able to draw each duck as a group, then simply SVG translate each group so it's aligned as a grid (instead of all ducks overlapping)
Additionally you might find sketch-rnn interesting since it uses the quickdraw dataset. In particular checkout David Ha's Sketch-RNN Colab notebook or his sketch-rnn/utils.py script. Even though the QuickDraw stroke format is slightly different from the sketch-rnn stroke format, there are still plenty of similarities and the links above include utility functions to draw an svg grid. They need adapting to QuickDraw's format.
If you're not constrained to Python alone and are comfortable with a bit of JavaScript the QuickDraw dataset README already inlcudes a link to a d3.js SVG demo

Removing the single pixels from Geotiff bianary image [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
This is classified image of satellite. Can anybody tell me how to remove these single pixels of filter out them. Remember this is in Geotiff format. I already applied erosion or dilation techniques but no success.
I saw a similar question on SO but can't find it. There were a quite good answer that I remade for myself. So here is the method called particle_filter that will be the solution for your problem:
def particle_filter(image_, power):
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image_, connectivity=8)
sizes = stats[1:, -1]
nb_components = nb_components - 1
min_size = power
img2 = np.zeros(output.shape, dtype=np.uint8)
for i in range(0, nb_components):
if sizes[i] >= min_size:
img_to_compare = threshold_gray_const(output, (i + 1, i + 1))
img2 = binary_or(img2, img_to_compare)
img2 = img2.astype(np.uint8)
return img2
def threshold_gray_const(image_, rang: tuple):
return cv2.inRange(image_, rang[0], rang[1])
def binary_or(image_1, image_2):
return cv2.bitwise_or(image_1, image_2)
All you need to do is to call this function and give your binary image as first parameter and filter power as the second.
A bit explanation: Whole method - is simply iterating over objects on an image, and if the area of one of an object is less than the power, then it is simply removed.
I would give a try Median Filter (cv2.medianBlur) which should remove single pixels, but might also have other effect. You need to test it with few different settings and decide if it does provide you acceptable result.
Kernel size should be odd for Median Filter, thus median is used on odd number of pixels (9 for size 3, 25 for size 5, 49 for size 7 and so on), therefore Median Filter never introduces new value, thus if you use binary image as input, you will get binary image as output.

How to split a picture in numpy array format? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have an image of shape (31278,25794,3). I would like to know how is possible to obtain MxN segment of the picture, using np functions. For example starting from:
I would like to obtain:
In numpy you can split a picture like you slice an array.
Here's an example with your image:
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
img = np.array(Image.open("cat.jpg"))
plt.imshow(img)
xs = img.shape[0]//2 # division lines for the picture
ys = img.shape[1]//2
# now slice up the image (in a shape that works well with subplots)
splits = [[img[0:xs, 0:ys], img[0:xs, ys:]], [img[xs:, 0:ys], img[xs:, ys:]]]
fig, axs = plt.subplots(2, 2)
for i in range(2):
for j in range(2):
axs[i][j].imshow(splits[i][j])
Keep in mind that the splits here are views into the original array, not arrays with new data, so changes you make to the views will change the original data. If you don't want this, you can do something to copy the data after slice up the array.

Plotting quantiles, median and spread using scipy and matplotlib [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am new to matplotlib, and I want to create a plot, with the following information:
A line joining the medians of around 200 variable length vectors (input)
A line joining the corresponding quantiles of these vectors.
A line joining the corresponding spread (largest and smallest points).
So basically, its somewhat like a continuous box plot.
Thanks!
Using just scipy and matplotlib (you tagged only those libraries in your question) is a little bit verbose, but here's how you would do it (I'm doing it only for the quantiles):
import numpy as np
from scipy.stats import mstats
import matplotlib.pyplot as plt
# Create 10 columns with 100 rows of random data
rd = np.random.randn(100, 10)
# Calculate the quantiles column wise
quantiles = mstats.mquantiles(rd, axis=0)
# Plot it
labels = ['25%', '50%', '75%']
for i, q in enumerate(quantiles):
plt.plot(q, label=labels[i])
plt.legend()
Which gives you:
Now, I would try to convince you to try the Pandas library :)
import numpy as np
import pandas as pd
# Create random data
rd = pd.DataFrame(np.random.randn(100, 10))
# Calculate all the desired values
df = pd.DataFrame({'mean': rd.mean(), 'median': rd.median(),
'25%': rd.quantile(0.25), '50%': rd.quantile(0.5),
'75%': rd.quantile(0.75)})
# And plot it
df.plot()
You'll get:
Or you can get all the stats in just one line:
rd.describe().T.drop('count', axis=1).plot()
Note: I dropped the count since it's not a part of the "5 number summary".

Categories