Is it possible to have black and white and color image on same window by using opencv? - image

Is it possible to have black-and-white and color image on same window by using opencv libraray? How can I have both of these images on same window?

fraxel's answer has solved the problem with old cv interface. I would like to show it using cv2 interface, just to understand how this easy in new cv2 module. (May be it would be helpful for future visitors). Below is the code:
import cv2
import numpy as np
im = cv2.imread('kick.jpg')
img = cv2.imread('kick.jpg',0)
# Convert grayscale image to 3-channel image,so that they can be stacked together
imgc = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
both = np.hstack((im,imgc))
cv2.imshow('imgc',both)
cv2.waitKey(0)
cv2.destroyAllWindows()
And below is the output I got:

Yes it is, here is an example, expaination in the comments:
import cv
#open color and b/w images
im = cv.LoadImageM('1_tree_small.jpg')
im2 = cv.LoadImageM('1_tree_small.jpg',cv.CV_LOAD_IMAGE_GRAYSCALE)
#set up our output and b/w in rgb space arrays:
bw = cv.CreateImage((im.width,im.height), cv.IPL_DEPTH_8U, 3)
new = cv.CreateImage((im.width*2,im.height), cv.IPL_DEPTH_8U, 3)
#create a b/w image in rgb space
cv.Merge(im2, im2, im2, None, bw)
#set up and add the color image to the left half of our output image
cv.SetImageROI(new, (0,0,im.width,im.height))
cv.Add(new, im, new)
#set up and add the b/w image to the right half of output image
cv.SetImageROI(new, (im.width,0,im.width,im.height))
cv.Add(new, bw, new)
cv.ResetImageROI(new)
cv.ShowImage('double', new)
cv.SaveImage('double.jpg', new)
cv.WaitKey(0)
Its in python, but easy to convert to whatever..

Small improvement to the code with modern writing
concatenate
instead of
hstack
that is discontinued (stack can also be used)
import cv2
import numpy as np
im = cv2.imread('kick.jpg')
img = cv2.imread('kick.jpg',0)
# Convert grayscale image to 3-channel image,so that they can be stacked together
imgc = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
both = np.concatenate((im,imgc), axis=1) #1 : horz, 0 : Vert.
cv2.imshow('imgc',both)
cv2.waitKey(0)
cv2.destroyAllWindows()

import cv2
img = cv2.imread("image.jpg" , cv2.IMREAD_GRAYSCALE)
cv2.imshow("my image",img)
cv2.waitkey(0)
cv2.destroyAllWindow
#The image file should be in the application folder.
#The output file will be 'my image' name.
#The bottom line is to free up memory.

Related

Save RGB values from multple cropped images in a csv file

I am trying to extract RGB values from multiple cropped images using a single image. I want to save these RGB values into a csv file. For the same I have written the code mentioned below and the image is also attached below (color.jpg). But this code saves only the last cropped image RGB values. I want to save the RGB values for all cropped images. Could anyone suggest to me what changes I have to make for this code?
Thank you in advance
Python code:
from __future__ import with_statement
import cv2
import numpy as np
import csv
#image_path
img_path="gr.jpg"
#read image
img_raw = cv2.imread(img_path)
#select ROIs function
ROIs = cv2.selectROIs("Select Rois",img_raw)
#print rectangle points of selected roi
print(ROIs)
#Crop selected roi ffrom raw image
#roi_cropped = img_raw[int(roi[1]):int(roi[1]+roi[3]), int(roi[0]):int(roi[0]+roi[2])]
#counter to save image with different name
crop_number=0
#loop over every bounding box save in array "ROIs"
for rect in ROIs:
x1=rect[0]
y1=rect[1]
x2=rect[2]
y2=rect[3]
#crop roi from original image
img_crop=img_raw[y1:y1+y2,x1:x1+x2]
b,g,r = cv2.split(img_crop)
#Average RGB of the cropped image
B = b.mean()
G = g.mean()
R = r.mean()
#show cropped image
cv2.imshow("crop"+str(crop_number),img_crop)
#save cropped image
cv2.imwrite("crop"+str(crop_number)+".jpg",img_crop)
#Open a file to write the pixel data
with open('output_file.csv', 'w', newline='') as f_output:
csv_output = csv.writer(f_output)
csv_output.writerow(["img_name", "R", "G", "B"])
csv_output.writerow(["crop"+str(crop_number), R, G, B])
crop_number+=1
#hold window
cv2.waitKey(0)
cv2.destroyAllWindows()
[color.jpg][1]
[1]: https://i.stack.imgur.com/DpJD5.jpg
I think you just want to open for "append":
with open('output_file.csv', 'a', newline='') as f_output:

Bokeh rotated image blocks underlying image

I'm placeing a rotated image on top of another image of different anchor point in the same figure. However the top image partially covers the bottom image, shown below. Is there a way to remove the black border of the rotated image?
Sample codes here:
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource, show
from bokeh.layouts import column
from bokeh.models.tools import PanTool, BoxZoomTool, WheelZoomTool, \
UndoTool, RedoTool, ResetTool, SaveTool, HoverTool
import numpy as np
from collections import namedtuple
from scipy import ndimage
def make_document(doc):
p = figure(match_aspect=True)
Anchor = namedtuple('Anchor', ['x', 'y'])
img1 = np.random.rand(256, 256)
anchor1 = Anchor(x=0, y=0)
img2= np.random.rand(256, 256)
anchor2 = Anchor(x=100, y=100)
img2 = ndimage.rotate(img2, 45, reshape=True)
p.image(image=[img1], x=anchor1.x, y=anchor1.y,
dw=img1.shape[0], dh=img1.shape[1], palette="Greys256")
p.image(image=[img2], x=anchor2.x, y=anchor2.y,
dw=img2.shape[0], dh=img2.shape[1], palette="Greys256")
doc.add_root(column(p, sizing_mode='stretch_both'))
apps = {'/': make_document}
server = Server(apps)
server.start()
server.io_loop.add_callback(server.show, "/")
try:
server.io_loop.start()
except KeyboardInterrupt:
print('keyboard interruption')
print('Done')
When you rotate an image, the new empty regions (black triangles on your image) are by default initialized with 0 (check out the mode and cval options at https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.rotate.html).
If you have a value that you know for sure will never be used in an image, you can pass it as cval. Then, you should be able to manually create a color mapper that maps that value to a transparent pixel and use the mapper instead of the palette (the arg name would be color_mapper).
If you don't have such a value, then you will have to use image_rgba and just make sure that whatever cval you decide to use will result in a transparent pixel.

skimage treshold_local does not work with pictures loaded using io.imread

I am was trying out one of the sample Python scripts available from the web site of Scikit Image. This script demonstrates Otsu segmentation at a local level. The script works with pictures loaded using
data.page()
but not using
io.imread
. Any suggestions?
https://scikit-image.org/docs/dev/auto_examples/applications/plot_thresholding.html#sphx-glr-auto-examples-applications-plot-thresholding-py
Picture file
Actual output - the Local thresholding window is empty
As you can see, Global thresholding has worked.But Local Thresholding has failed to produce any results.
Strangely, if I use data.page() then everything works fine.
Script
from skimage import io
from skimage.color import rgb2gray
import matplotlib.pyplot as plt
from skimage.filters import threshold_otsu,threshold_local
import matplotlib
from skimage import data
from skimage.util import img_as_ubyte
filename="C:\\Lenna.png"
mypic= img_as_ubyte (io.imread(filename))
#image = data.page() #This works - why not io.imread ?
imagefromfile=io.imread(filename)
image = rgb2gray(imagefromfile)
global_thresh = threshold_otsu(image)
binary_global = image > global_thresh
block_size = 35
local_thresh = threshold_local(image, block_size, offset=10)
binary_local = image > local_thresh
fig, axes = plt.subplots(nrows=3, figsize=(7, 8))
ax = axes.ravel()
plt.gray()
ax[0].imshow(image)
ax[0].set_title('Original')
ax[1].imshow(binary_global)
ax[1].set_title('Global thresholding')
ax[2].imshow(binary_local)
ax[2].set_title('Local thresholding')
for a in ax:
a.axis('off')
plt.show()
If you load the lenna.png and print its shape you will see it is a 4-channel RGBA image rather than a 3-channel RGB image.
print mypic.shape
(512, 512, 4)
I am not sure which parts of your code apply to which image, so I am not sure where to go next, but I guess you want to just get the RGB part and discard the alpha:
RGB = mypic[...,:3]

Joining edited images in python using numpy image slicer

I am learning image manipulation as a beginner in python. My goal is to section my image into an nxn grid where each square is the average color (greyscale image) of the original, respectively. I succeeded in splitting the image, changing its pixel data and saving the new images. My problem is now stitching the image back together. I know the join function is pointing back to the original image, I had hoped that by saving over the tiles I could work around this.
This is my first time posting to stackoverflow (and I am super, super new to python), so apologies if I am not clear or if the formatting is wrong.
# Import packages
import numpy as np
from numpy import matlib
import PIL
import image_slicer
import math
import glob
from image_slicer import join
from PIL import Image
### Use PIL to import image
##img = Image.open("einstein.jpg")
# Display original image
# img.show()
##new_img = img.resize((256,256))
##new_img.save('einstein-256x256','png')
### new_img.show()
#Slice image into four pieces
tiles = image_slicer.slice("einstein.jpg", 16)
# Use glob to open every .png file with for loop
for filename in glob.glob("*.png"):
img=Image.open(filename)
pixels = img.load() # create the pixel map
pixelMap = img.load() #create the pixel map
#convert to array
arr = np.asarray(img)
#find mean
pixelMean = arr.mean(0).mean(0)[0]
# Convert mean to integer
IntMean = math.floor(pixelMean)
print(IntMean)
##pixel = pixelMap[0,0] #get the first pixel's value
##print(pixel)
# Loop for going through every pixel in image and converting it
for i in range(img.size[0]): # for every col:
for j in range(img.size[1]): # For every row
pixels[i,j] = (IntMean,IntMean,IntMean) # set the colour accordingly
# Save new monotone images
img.save(filename)
# Join new images into one
image = join(tiles)
# Save new image
image.save("einsteinJoined.jpg")
image.show()
Your question seems to be missing the error you get with your current code.
However, if I read it correctly, you will get back your original image, as was the problem in Split and Join images in Python. Similar to the answer accepted there, the solution is to change the image in each tile by ending your loop with:
tile.image = Image.open(filename)
Where tile is the tile corresponding to the file, you should loop over the tiles from the image_slicer.slice-function to do so. This is also given in answer to the question linked to.

pyplot.imsave() saves image correctly but cv2.imwrite() saved the same image as black

from scipy.misc import imread
from matplotlib import pyplot
import cv2
from cv2 import cv
from SRM import SRM ## Module for Statistical Regional Segmentation
im = imread("lena.png")
im2 = cv2.imread("lena.png")
print type(im), type(im2), im.shape, im2.shape
## Prints <type 'numpy.ndarray'> <type 'numpy.ndarray'> (120, 120, 3) (120, 120, 3)
srm = SRM(im, 256)
segmented = srm.run()
srm2 = SRM(im2, 256)
segmented2 = srm2.run()
pic = segmented/256
pic2 = segmented2/256
pyplot.imshow(pic)
pyplot.imsave("onePic.jpg", pic)
pic = pic.astype('uint8')
cv2.imwrite("onePic2.jpg", pic2)
pyplot.show()
onePic.jpg gives the correct segmented image but onePic2.jpg gives a complete black image.
Converting the datatype to uint8 using pic = pic.astype('uint8') did not help. I still gives a black image!
onePic.jpg using pyplot.imsave():
onePic2.jpg using cv2.imwrite():
Please help!
Before converting pic to uint8, you need to multiply it by 255 to get the correct range.
Although I agree with #sansuiso, in my case I found a possible edge case where my images were being shifted either one bit up in the scale or one bit down.
Since we're dealing with unsigned ints, a single shift means a possible underflow/overflow, and this can corrupt the whole image.
I found cv2's convertScaleAbs with an alpha value of 255.0 to yield better results.
def write_image(path, img):
# img = img*(2**16-1)
# img = img.astype(np.uint16)
# img = img.astype(np.uint8)
img = cv.convertScaleAbs(img, alpha=(255.0))
cv.imwrite(path, img)
This answer goes into more detail.
I encountered a similar situation with face detection, I wonder if there is a better way to execute this, here is my solution here as a reference.
from deepface import DeepFace
import cv2
import matplotlib.pyplot as plt
# import image and output
img_path = "image.jpg"
detected_face = DeepFace.detectFace(img_path, target_size = (128, 128))
plt.imshow(detected_face)
# image color scaling and saving
detected_face = cv2.cvtColor( detected_face,cv2.COLOR_BGR2RGB)
detected_face = cv2.convertScaleAbs(detected_face, alpha=(255.0))
cv2.imwrite("image_thumbnail.jpg", detected_face)

Resources