I want to compare a plot from a paper to my simulation results.
Therefore it would be convenient to plot my results with the ref pic in the background.
the x value range i choose to be the same as the ref pic
y should also be close to the ref pic.
Or i can set the y range also to the same values as the ref pic.
i tryed
x=range(len(P))
plt.plot(x,P)
img=plt.imread("REF.jpg")
plt.imshow(img)
plt.show()
But it chooses the scale i think according to pixels?
and my other plot was a miniature on it.
if i use extend and one dimension is much larger then the other, one can see nothing on the pic because of the bad aspect ratio
Related
If I have an image in the form of [556,556] PX and I would like to plot a certain range of them so say:
Image Size: [556,556]
Plot -> XPixels [224,300] YPixels [224,300]
This was my attempt and it does sort-of what I need it to do, I have the correct pixels selected but unfortunately this only labels the given range and doesn't actually plot the range. Understandably the next part of this would be to plot the new range given the image but how would I go about this?
openDicom = pdi.dcmread(filePath)
plt.imshow(openDicom.pixel_array, cmap=plt.cm.Spectral, origin = 'lower',interpolation = 'nearest')
plt.xticks([308,341])
plt.yticks([234,271])
Please see my "Amazing Drawing" for further reference. Thanks!
Just pass the array sub area to imshow.
plt.imshow(image[y_start:y_end, x_start:x_end])
A chem student asked me for help with plotting image segmenetation:
A stationary camera takes a picture of the experimental setup every second over a period of a few minutes, so like 300 images yield.
The relevant parts in the setup are two adjacent layers of differently-colored foams observed from the side, a 2-color sandwich shrinking from both sides, basically, except one of the foams evaporates a bit faster.
I'd like to segment each of the images in the way that would let me plot both foam regions' "width" against time.
Here is a "diagram" :)
I want to go from here --> To here
Ideally, given a few hundred of such shots, in which only the widths change, I get an array of scalars back that I can plot. (Going to look like a harmonic series on either side of the x-axis)
I have a bit of python and matlab experience, but have never used OpenCV or Image Processing toolbox in matlab, or actually never dealt with any computer vision in general. Could you guys throw like a roadmap of what packages/functions to use or steps one should take and i'll take it from there?
I'm not sure how to address these things:
-selecting at which slice along the length of the slice the algorithm measures the width(i.e. if the foams are a bit uneven), although this can be ignored.
-which library to use to segment regions of the image based on their color, (some k-means shenanigans probably), and selectively store the spatial parameters of the resulting segments?
-how to iterate that above over a number of files.
Thank you kindly in advance!
Assume your Intensity will be different after converting into gray scale ( if not, just convert to other color space like HSV or LAB, then just use one of the components)
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
First, Threshold your grayscaled input into a few bands
ret,thresh1 = cv.threshold(img,128,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img,27,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img,77,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img,97,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img,227,255,cv.THRESH_TOZERO_INV)
The value should be tested out by your actual data. Here Im just give a example
Clean up the segmented image using median filter with a radius larger than 9. I do expect some noise. You can also use ROI here to help remove part of noise. But personally I`m lazy, I just wrote program to handle all cases and angle
threshholed_images_aftersmoothing = cv2.medianBlur(threshholed_images,9)
Each band will be corresponding to one color (layer). Now you should have N segmented image from one source. where N is the number of layers you wish to track
Second use opencv function bounding rect to find location and width/height of each Layer AKA each threshholed_images_aftersmoothing. Eg. boundingrect on each sub-segmented images.
C++: Rect boundingRect(InputArray points)
Python: cv2.boundingRect(points) → retval¶
Last, the rect have x,y, height and width property. You can use a simple sorting order to sort from top to bottom layer based on rect attribute x. Run though all vieo to obtain the x(layer id) , height vs time graph.
Rect API
Public Attributes
_Tp **height** // this is what you are looking for
_Tp width
_Tp **x** // this tells you the position of the band
_Tp y
By plot the corresponding heights (|AB| or |CD|) over time, you can obtain the graph you needed.
The more correct way is to use Kalman filter to track the position and height graph as I would expect some sort of bubble will occur and will interfere with the height of the layers.
To be honest, i didnt expect a chem student to be good at this. Haha good luck
Anything wrong you can find me here or Email me if i`m not watching stackoverflow
You can select a region of interest straight down the middle of the foams, a few pixels wide. If you stack these regions for each image it will show the shrink over time.
If for example you use 3 pixel width for the roi, the result of 300 images will be a 900 pixel wide image, where the left is the start of the experiment and the right is the end. The following image can help you understand:
Though I have not fully tested it, this code should work. Note that there must only be images in the folder you reference.
import cv2
import numpy as np
import os
# path to folder that holds the images
path = '.'
# dimensions of roi
x = 0
y = 0
w = 3
h = 100
# store references to all images
all_images = os.listdir(path)
# sort images
all_images.sort()
# create empty result array
result = np.empty([h,0,3],dtype=np.uint8)
for image in all_images:
# load image
img = cv2.imread(path+'/'+image)
# get the region of interest
roi = img[y:y+h,x:x+w]
# add the roi to previous results
result = np.hstack((result,roi))
# optinal: save result as image
# cv2.imwrite('result.png',result)
# display result - can also plot with matplotlib
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Update after question edit:
If the foams have different colors, your can use easily separate them by color by converting the image you hsv and using inrange (example). This creates a mask (=2D array with values from 0-255, one for each pixel) that you can use to calculate average height and extract the parameters and area of the image.
You can find a script to help you find the HSV colors for separation on this GitHub
I have a dataset which has a different range of the x coordinate at each y coordinate, without a specific rule or a fixed delta_x. E.g.
y=0 -> x is 40 values in range(20, 55)
y=1 -> x is 40 values in range(24, 49)
y=2 -> x is 40 values in range(23, 59)
...
Is there a way to get a checkerboard plot with such data using imshow?
I have tried changing the extent at each y value in a loop, but this just shifts each row to the last extent i set. In the plots below, the horizontal extent at the top should be [1410, 2190], and the horizontal extent at the bottom is [1453, 4970]. The red and white lines are a simple plot on top, and should follow the area shaded in red and yellow. See image here
I have tried using tricontourf (after Oliver W.'s suggestion here), which handles the dataset fine, the plot is accurate. You can also see how the horizontal extent changes. There are some artifacts in the image however. I'd like to use rectangles without interpolation, instead of interpolated triangles, if possible. See image here
I have tried appending the minimum and maximum values of all x at each y, and using those values for the horizontal extent, and it kinda works. See image here
It's still not accurate, and I'm not sure why. I can get a slightly better/more correct image by changing the values manually, first try. See image here
I'd be grateful for any comments or suggestions.
I have a (geographic) raster-image in RGB. I also have an external legend displaying the heights according to a certain color. In below figure, I have sampled this legend, hopefully revealing its RGB-characteristics. I have plotted these values to their actual height values on the X-axis.
Now, is it possible to directly derive height from the pixel's RGB-value? Ultimately, I'm looking for a simple formula which is able to translate my RGB values into one height value (e.g. H = aR + bG + c*B) Any hint or tips? Is it even possible at all?
I have a map with a scale like this one: (the numbers are just an example)
which describes a single variable on a map. However, I don't have access to the original data and know pretty close to nothing
about image processing. What I have done is use PIL to get the pixel-coordinates and RGB values of each point on the map. Simply using pix = im.load() and saving pix[x,y] for each x,y. Now I would like to guess the value of each point using the gradient above.
Is there a standard formula for such a gradient? Does it look very familiar to the trained eye? I have visited Digital Library of Mathematical Functions for some examples ... but I'm not sure if it's using the hue, the rgb height function or something else (to make things easier I'm also colorblind to some greens/brows/reds) :)
Any tips on how to proceed, libraries, links or ideas are appreciated. Thank you!
edit:
Following the replies and martineau's suggestion, I've tried to catch the colors at the top and bottom:
def rgb2hls(colotup):
'''converts 225 based RGB to 360 based HLS
`input`: (222,98,32) tuple'''
dec_rgb = [x/255.0 for x in colotup] # use decimal 0.0 - 1.0 notation for RGB
hsl_col = colorsys.rgb_to_hls(dec_rgb[0], dec_rgb[1], dec_rgb[2])
# PIL uses hsl(360,x%,y%) notation and throws errors on float, so I use int
return (int(hsl_col[0]*360), int(hsl_col[1]*100), int(hsl_col[2]*100))
def pil_hsl_string(hsltup):
'''returns a string PIL can us as HSL color
from a tuple (x,y,z) -> "hsl(x,y%,z%)"'''
return 'hsl(%s,%s%%,%s%%)' % (hsltup[0], hsltup[1], hsltup[2])
BottomRed = (222,98,32) # taken with gimp
TopBlue = (65, 24, 213)
hue_red = pil_hsl_string(rgb2hls(BottomRed))
hue_blue = pil_hsl_string(rgb2hls(TopBlue))
However they come out pretty different ... which makes me worry about using the rgb_to_hls function to extract the values. Or I'm I doing something very wrong? Here's what the color s convert to with the code:
Interesting question..
If you do a clock-wise walk in HSL color-space from 250,85%,85% --> 21,85%,85% you get a gradient very close to the one you've shown. The obvious difference being that your image exhibits a fairly narrow band of greenish values.
So, if you have the 4 magic numbers then you can interpolate to any point within the map.
These of course being the first and last colour, also the first and last scale value.
Here's the image I got with a straight linear gradient on the H channel (used the gimp).
EDIT: I've since whipped up a program to grab the pixel values for each row, graphing the results. You can see that indeed, the Hue isn't linear, you can also see the S & V channels taking a definite dip at around 115 (115 pixels from top of image) This indeed corresponds with the green band.
Given the shape of the curves, I'm inclined to think that perhaps they are intended to model something. But don't have the experience in related fields to recognise the shape of the curves.
Below, I've added the graphs for the change in both the HSV and RGB models.
The left of the graph represents the top of the bar.
The X-axis labels represent pixels
Quite interesting, me thinks. Bookmarked.
The scale in the image looks like an HSV gradient to me, something like what is mentioned in this question. If so, you could use the colorsys.rgb_to_hls() or colorsys.rgb_to_hsv() functions to obtain a hue color value between 0 and 1 from the r,g,b values in a pixel. That can then be mapped accordingly.
However, short of doing OCR, I have no idea how to determine the range of values being represented unless it's some consistent range you can just hardcode.
I would recomend to define an area where you want to compare the colour. Take an FFT of the regions. Each colour is defined by a frequency. You do the same on the countour scale. then compare and narrow on a value.
I have found some like to understand it better.
http://www.imagemagick.org/Usage/fourier/
You can get something like that by varying the hue with a fixed saturation and luminance.
http://en.wikipedia.org/wiki/HSL_and_HSV