share pic link: https://imgur.com/a/yyQChWQ
If I have black gradient img , we know the RGB is (0 ~ 255) or HSV is (0 ~ 255)
How can I make close color range color together
such as ( 0 ~ 80), ( 80 ~ 160) , ( 160 ~ 255)
expect output:
1. I want the output to be (expect pic in link) (to remove noise)
2. generate histogram for (original pic) in 1D not 3D that too complicate I can't understand
here is the .py script can show HSV and RGB of pic, I saved the result in share pic link
import numpy as np
import cv2
import matplotlib.pyplot as plt
def show_img(path):
img = cv2.imread(path)
b, g, r = img[:,:,0], img[:,:,1], img[:,:,2]
hist_b = cv2.calcHist([b],[0],None,[256],[0,256])
hist_g = cv2.calcHist([g],[0],None,[256],[0,256])
hist_r = cv2.calcHist([r],[0],None,[256],[0,256])
plt.plot(hist_r, color='r', label="r")
plt.plot(hist_g, color='g', label="g")
plt.plot(hist_b, color='b', label="b")
plt.legend()
plt.show()
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = img2[:,:,0], img2[:,:,1], img2[:,:,2]
hist_h = cv2.calcHist([h],[0],None,[256],[0,256])
hist_s = cv2.calcHist([s],[0],None,[256],[0,256])
hist_v = cv2.calcHist([v],[0],None,[256],[0,256])
plt.plot(hist_h, color='r', label="h")
plt.plot(hist_s, color='g', label="s")
plt.plot(hist_v, color='b', label="v")
plt.legend()
plt.show()
return hist_r,hist_g, hist_b, hist_h, hist_s, hist_v
aaa = "/home/student_DC/desktop/optimization_11_10/output_11_10__002/22.png"
r,g,b,h,s,v = show_img(aaa)
My suggestion is to use a grayscale image so that all the computations and displays are easier:
import numpy as np
import cv2
import matplotlib.pyplot as plt
path = "**/RKqsXEv.png"
# Read the image in grayscale
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
img_filtered = img.copy()
# Simple editing through a loop on pixels value
for i in range (img.shape[0]):
for j in range(img.shape[1]):
if (img[i,j] < 80):
img_filtered[i,j] = 40
elif (img[i,j] < 160):
img_filtered[i,j] = 120
else:
img_filtered[i,j] = 200
plt.imshow(img_filtered, cmap='gray')
plt.show()
# Calculate a 1D histogram on the grayscale image
hist = cv2.calcHist(img, [0], None, [255], [0,255])
plt.plot(hist)
plt.show()
Output:
Related
I need to find and split each shelves from planogram image. In this case split using blue(it can be black, gray, etc.) lines so it should give me 8 shelves. I tried using Hough lines, contours to recognize the shelf. Tell me, please, how to recognize shelves.
Here's my code:
import cv2
import numpy as np
# Load the image
img = cv2.imread("display.jpg")
# Convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Threshold the image to binarize it
threshold, binary = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV)
# Find contours
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Loop through each contour
for i, contour in enumerate(contours):
# Get bounding box of contour
x, y, w, h = cv2.boundingRect(contour)
# Crop the image to the bounding box
shelf_img = img[y:y+h, x:x+w]
# Save the cropped image
cv2.imwrite(f"shelf_{i}.jpg", shelf_img)
Here's the second approach:
#!/usr/bin/env python
# coding: utf-8
# In[5]:
from skimage.transform import (hough_line, hough_line_peaks,probabilistic_hough_line)
from skimage.feature import canny
from skimage import data
from skimage.io import imread
import numpy as np
import matplotlib.pyplot as plt
from skimage.filters import roberts, sobel, scharr
# In[6]:
image = imread("display.jpg", as_gray=True) * 255
# In[7]:
edges = canny(image, 4, 1, 25)
lines = probabilistic_hough_line(edges, threshold=2, line_length=10, line_gap=3)
fig2, ax = plt.subplots(1, 3, figsize=(20, 8))
ax[0].imshow(image, cmap=plt.cm.gray)
ax[0].set_title('Input image')
ax[0].axis('image')
ax[1].imshow(edges, cmap=plt.cm.gray)
ax[1].set_title('Canny edges')
ax[1].axis('image')
ax[2].imshow(edges * 0)
for line in lines:
p0, p1 = line
ax[2].plot((p0[0], p1[0]), (p0[1], p1[1]))
ax[2].set_title('Probabilistic Hough')
ax[2].axis('image')
# In[8]:
height, width = image.shape
# In[9]:
def proj_x(line):
p0, p1 = line
return np.abs(p0[0] - p1[0])
def proj_y(line):
p0, p1 = line
return np.abs(p0[1] - p1[1])
# In[10]:
s_h = np.zeros(height)
s_v = np.zeros(height)
for line in lines:
p0, p1 = line
y1 = max(p0[1], p1[1])
y0 = min(p0[1], p1[1])
if proj_y(line) > 2:
s_v[y0: y1] += proj_y(line)
if proj_x(line) > 2:
s_h[y0: y1] += proj_x(line)
# In[11]:
#fig2, ax = plt.subplots(1, 2, figsize=(8, 8))
plt.figure(figsize=(20, 10))
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Input image')
plt.plot(s_h, np.arange(height), linewidth=2, label="s_h")
plt.plot(s_v, np.arange(height), linewidth=2, label="s_v")
plt.ylim([height, 0])
plt.xlim([0, width])
plt.legend()
# In[13]:
import scipy.ndimage
s_f = 20 * s_h / (s_v + 1)
s_f = scipy.ndimage.gaussian_filter1d(s_f, 1)
# In[14]:
plt.figure(figsize=(20, 10))
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Input image')
plt.plot(s_f, np.arange(height), linewidth=2, label="s_h")
plt.ylim([height, 0])
plt.xlim([0, width])
# In[15]:
import scipy.signal
# In[26]:
cands = scipy.signal.find_peaks_cwt(s_f, np.arange(1, 50))
print(zip(cands, s_f[cands]))
# In[18]:
pairs = []
for c in cands:
for d in cands:
if (c < d) and (d -c < 100):
pairs.append((c, d))
# In[19]:
y_tagets = pairs[np.argmax([s_f[a] * s_f[b] for a, b in pairs])]
# In[20]:
y0, y1 = y_tagets
# In[21]:
import matplotlib.patches as patches
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, aspect='equal')
ax.imshow(image, cmap=plt.cm.gray)
ax.set_title('Input image')
ax.add_patch(
patches.Rectangle(
(0, y0),
width,
y1 - y0,
facecolor="red",
alpha=0.4 # remove background
)
)
I am trying to apply the Butterworth low pass filter on the image but for some reason the values in lpFilter is not copied in lpFilter_matrix I tried to do it with a nested loop but still didn't work and the values of lpFilter_matrix remained zero.
import cv2
import numpy as np
from matplotlib import pyplot as plt
image=cv2.imread(r"C:/Users/Admin/Pictures/eee.jpg",0)
image_float32=np.float32(image)
dft =cv2.dft(image_float32,flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift=np.fft.fftshift(dft)
magnitude_spectrum=np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
rows, cols = image.shape
crow, ccol = rows//2 , cols//2
r, c = np.mgrid[0:rows:1, 0:cols:1]
c -= crow
r -= ccol
d = np.sqrt(np.power(r, 2.0) + np.power(c, 2.0))
lpFilter_matrix = np.zeros((rows, cols, 2), np.uint8)
d0=10
n=2
lpFilter = 1.0 / (1 + np.power(d/d0, 2*n))
lpFilter_matrix[:, :, 0] = lpFilter
lpFilter_matrix[:, :, 1] = lpFilter
fshift = dft_shift*lpFilter_matrix
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.figure(figsize=(14,9))
plt.subplot(121)
plt.imshow(image, cmap = 'gray')
plt.title('Input Image')
plt.axis('off')
plt.subplot(122)
plt.imshow(img_back, cmap = 'gray')
plt.title('filtered Image')
plt.axis('off')
I think your issue is that your filter needs to be float and not 8-bit. So as I said in my comment, change this line.
lpFilter_matrix = np.zeros((rows, cols, 2), np.uint8) with lpFilter_matrix = np.zeros((rows, cols, 2), np.float32)
So this works for me in Python/OpenCV.
Input:
import cv2
import numpy as np
from matplotlib import pyplot as plt
# read image as grayscale and convert to float
image=cv2.imread("lena.jpg",0)
image_float32=np.float32(image)
# do dft
dft =cv2.dft(image_float32,flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift=np.fft.fftshift(dft)
# get the magnitude
magnitude_spectrum=np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
# initialize filter and center it
rows, cols = image.shape
crow, ccol = rows//2 , cols//2
r, c = np.mgrid[0:rows:1, 0:cols:1]
c -= crow
r -= ccol
# make filter circular
d = np.sqrt(np.power(r, 2.0) + np.power(c, 2.0))
lpFilter_matrix = np.zeros((rows, cols, 2), np.float32)
# specify filter arguments
d0=10
n=2
# compute butterworth filter
lpFilter = 1.0 / (1 + np.power(d/d0, 2*n))
lpFilter_matrix[:, :, 0] = lpFilter
lpFilter_matrix[:, :, 1] = lpFilter
# apply filter
fshift = dft_shift*lpFilter_matrix
# do idft
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
# convert back to real output from complex
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
fig = plt.figure(figsize=(14,9))
plt.subplot(121)
plt.imshow(image, cmap = 'gray')
plt.title('Input Image')
plt.axis('off')
plt.subplot(122)
plt.imshow(img_back, cmap = 'gray')
plt.title('filtered Image')
plt.axis('off')
plt.show()
fig.savefig('lena_butterworth.jpg')
plt.close(fig)
Results:
Im trying to crop rectangle image from screenshot, background for image must be white, Im ending up having black,How can I change that? I want to make histogtam of rgb for the final image and It seems plotting only vertical line on zero, Any kind of help is very important! here is my code:
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
image = cv2.imread(filename = "Screenshot from 2019-11-08 22-02-27.png")
mask = np.zeros(shape = image.shape, dtype = "uint8")
cv2.rectangle(img = mask,
pt1 = (0, 185), pt2 = (1900, 773),
color = (255, 255, 255),
thickness = -1)
maskedImg = cv2.bitwise_and(src1 = image, src2 = mask)
cv2.imwrite("processed.png", maskedImg)
plt.imshow(maskedImg)
plt.show()
plt.hist(maskedImg.ravel(),256,[0,256]); plt.show()
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
image = cv2.imread(filename = "1.png")
mask = np.zeros(shape = image.shape, dtype = "uint8")
cv2.rectangle(img = mask,
pt1 = (0, 185), pt2 = (1900, 773),
color = (255, 255, 255),
thickness = -1)
maskedImg = cv2.bitwise_and(src1 = image, src2 = mask)
maskedImg[np.where((maskedImg==[0,0,0]).all(axis=2))] = [255,255,255]
cv2.imwrite("processed.png", maskedImg)
plt.imshow(maskedImg)
plt.show()
Convert the black pixel present in the image into white pixel
Original image
Crop Image
color = ('b','g','r')
for i,col in enumerate(color):
histr = cv2.calcHist([maskedImg],[i],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.show()
I'm trying to convert a figure created with Matplotlib imshow into RGBA values but I got the following error:
ValueError: not enough values to unpack (expected 4, got 0)
This is my code:
speed0 = speed[0, :, :].values
figsize = (7, 7)
cbarkw = dict(shrink=0.6, extend='both')
fig, ax = plt.subplots(figsize=figsize)
i = plt.imshow(speed0, origin='lower')
cbar = plt.colorbar(i, **cbarkw)
plt.axis('off')
def matplotlib_to_opencv(i):
image = i._rgbacache
r, g, b, a = cv2.split(image)
return np.flipud(cv2.merge([b, g, r, a]))
image = matplotlib_to_opencv(i)
Where speed0 is a wind dataset of (192x111). I think 'image' is a null cache and hence cv2.split can't read it but I don't know how to make it work properly. Ideas?
Thank you in advance.
What I think you should do to get what you want is change the call to make_image
import numpy as np
import matplotlib.pyplot as plt
import cv2
speed = np.random.random((4, 192, 111))
speed0 = speed[0, :, :]
figsize = (7, 7)
cbarkw = dict(shrink=0.6, extend='both')
fig, ax = plt.subplots(figsize=figsize)
im = plt.imshow(speed0, origin='lower')
cbar = plt.colorbar(im, **cbarkw)
plt.axis('off')
def matplotlib_to_opencv(im):
image = im.make_image('TkAgg')
# this returns
# -------
# image : (M, N, 4) uint8 array
# The RGBA image, resampled unless *unsampled* is True.
# x, y : float
# The upper left corner where the image should be drawn, in pixel
# space.
# trans : Affine2D
# The affine transformation from image to pixel space.
# """
# So you just want the first
r, g, b, a = cv2.split(image[0])
return np.flipud(cv2.merge([b, g, r, a]))
image = matplotlib_to_opencv(im)
plt.show()
Since I did not have your dataset I'm not 100% sure this is what you wanted. But I believe it should work.
I used histogram equalization and adaptation for erase illumination from the grayscale images, but after the histogram equalization (i used scikit image python library) was good, during image conversion in mahotas something goes wrong. I got a picture total black. How can i fix it?
Source image:
Histogram equalization and adaptation;
Result after mahotas conversion.
conversion code from scikit to mahotas:
binimg = np.array(img_adapteq, dtype=np.bool)
Source code:
import scipy
import numpy as np
import pymorph as pm
import mahotas as mh
from skimage import morphology
from skimage import io
from matplotlib import pyplot as plt
from skimage import data, img_as_float
from skimage import exposure
def plot_img_and_hist(img, axes, bins=256):
"""Plot an image along with its histogram and cumulative histogram.
"""
img = img_as_float(img)
ax_img, ax_hist = axes
ax_cdf = ax_hist.twinx()
# Display image
ax_img.imshow(img, cmap=plt.cm.gray)
ax_img.set_axis_off()
# Display histogram
ax_hist.hist(img.ravel(), bins=bins, histtype='step', color='black')
ax_hist.ticklabel_format(axis='y', style='scientific', scilimits=(0, 0))
ax_hist.set_xlabel('Pixel intensity')
ax_hist.set_xlim(0, 1)
ax_hist.set_yticks([])
# Display cumulative distribution
img_cdf, bins = exposure.cumulative_distribution(img, bins)
ax_cdf.plot(bins, img_cdf, 'r')
ax_cdf.set_yticks([])
return ax_img, ax_hist, ax_cdf
mhgray = mh.imread(path,0)
binimg = mhgray[:,:,0]
print(type(binimg[0][0]))
thresh = mh.otsu(binimg)
gray =( binimg< thresh)
shape = list(gray.shape)
w = 0
if (shape[0] > shape[1]):
shape = shape[0]
else:
shape = shape[1]
if (shape < 100):
w = int((shape/100 )*1.5)
elif(shape > 100 and shape <420):
w = int((shape/100 )*2.5)
else:
w = int((shape/100)*4)
disk7 = pm.sedisk(w)
img = binimg
# Contrast stretching
p2 = np.percentile(img, 2)
p98 = np.percentile(img, 98)
img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98))
# Equalization
img_eq = exposure.equalize_hist(img)
# Adaptive Equalization
img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
# Display results
f, axes = plt.subplots(2, 4, figsize=(8, 4))
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0])
ax_img.set_title('Low contrast image')
y_min, y_max = ax_hist.get_ylim()
ax_hist.set_ylabel('Number of pixels')
ax_hist.set_yticks(np.linspace(0, y_max, 5))
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1])
ax_img.set_title('Contrast stretching')
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2])
ax_img.set_title('Histogram equalization')
ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_adapteq, axes[:, 3])
ax_img.set_title('Adaptive equalization')
ax_cdf.set_ylabel('Fraction of total intensity')
ax_cdf.set_yticks(np.linspace(0, 1, 5))
# prevent overlap of y-axis labels
plt.subplots_adjust(wspace=0.4)
plt.show()
plt.gray()
plt.subplot(121)
plt.title("after histo")
plt.imshow(img_adapteq)
plt.show()
binimg = np.array(img_adapteq, dtype=np.bool)#uint16
plt.gray()
plt.subplot(121)
plt.title("after otsu")
plt.imshow(binimg)
plt.show()
imgbnbin = mh.morph.dilate(binimg, disk7)
#2
plt.gray()
plt.subplot(121)
plt.title("after dilate before close")
plt.imshow(imgbnbin)
plt.show()
imgbnbin = mh.morph.close(imgbnbin, disk7)
#2
plt.gray()
plt.subplot(121)
plt.title("before skeletonize")
plt.imshow(imgbnbin)
plt.show()
imgbnbin = mh.morph.close(imgbnbin, disk7)
out = morphology.skeletonize(imgbnbin>0)
The scikit-image algorithm probably returns a floating point image with values between 0 and 1. If you cast that to bool, you'll get all ones. You probably want
binimg = img_adapteq > 0.5
In general, also take note of the rescale_intensity function, which will take an image with values between 0 and 1 and return an image with values between 0 and 255.
from skimage import exposure
image = rescale_intensity(image, out_range=(0, 255))