I'm coding a program which'll take an image for an input, check it against images in a database and output the image with the same hash
However, when using hash("imagepath") 2 of the same images give different hashes, even when the only difference is the image's name, which makes me believe the name is the issue
Is there a way to easily ignore the name of the image? (png)
How I solved it:
I ended up not using "hashing" but the average pixel by scrambeling pieces of code together, and then find an image with the same average pixel (the average pixels are in a list so it gets the index which it then uses to find a name)
import requests
#Database of possible image average pixels
clone_imgs = [88.0465, 46.2568, 102.6426 ...]
image = <image url>
img_data = requests.get(image).content
with open('image.png', 'wb') as handler: #Download the image as "image.png" (Replace "image.png" with the path where you want to save it)
handler.write(img_data)
img = Image.open(r"image.png") #Open the image for reading
img = img.resize((100, 100), Image.ANTIALIAS) #A series of compressions to the image
img = img.convert("L")
img_pixel_data = list(spawn.getdata())
img_avg_pixel = sum(spawn_pixel_data)/len(spawn_pixel_data) #Get the average pixel values
clone_img_index = clone_imgs.index(img_avg_pixel) #Find the same pixel value in the database
This worked for me but it has a few downsides:
The images need to be 100% the same in color (A single pixel off can ruin it)
One of these average pixels can make an infinite amount of images, my database only contained 800 so it still worked (However I had to go from compression to 10x10 to 100x100 to not end up with clones)
Related
So, I extracted the radiometric raw data of thermograms (exiftools) and needed to do some processing to enhance the visualization in order to annotate these images to get mask for segmentation later. However, I need to keep the radiometric values unchanged (they are 16bits grayscale thermal images). The extracted raw png is too gray and I barely can see the image, so I thought on doing some basic processing (min-max normalization) to enhance the visualization. For this image, for example, the max and min values range from 19663 to 16792, but it varies. When I normalize using mix/max (code below) the image looks great for annotation, but it stretches the values and I don't want it.
Im using this loop to process these images:
for filename in glob.iglob("*.png"):
if "raw" in filename:
img = cv2.imread(filename, -1)
#max = np.max(img)
#min = np.min(img)
img_16bits = cv2.normalize(img, None, 0, 65535, cv2.NORM_MINMAX, dtype = cv2.CV_16U)
basename = os.path.splitext(os.path.basename(filename))[0]
cv2.imwrite(basename+"_"+"16bits"+".png",img_16bits)
Interesting enough, when I plot the image using plt.imshow with grayscale cmap, the image looks great and the values are unchanged, same when I drag it in ImageJ (it automatically corrects the contrast). I tried several things to change this code to get where I want, without luck. Any help would be appreciated. Thanks.
Images (raw image / processed with stretched values):
I want to resize png picture 476x402 to 439x371, and I used resize method of PIL(image) or opencv, however, it will loss some sharp. After resize, The picture becomes blurred.
How to resize(shrink) image without losing sharpness with use python?
from skimage import transform, data, io
from PIL import Image
import os
import cv2
infile = 'D:/files/script/org/test.png'
outfile = 'D:/files/script/out/test.png'
''' PIL'''
def fixed_size1(width, height):
im = Image.open(infile)
out = im.resize((width, height),Image.ANTIALIAS)
out.save(outfile)
''' open cv'''
def fixed_size2(width, height):
img_array = cv2.imread(infile)
new_array = cv2.resize(img_array, (width, height), interpolation=cv2.INTER_CUBIC)
cv2.imwrite(outfile, new_array)
def fixed_size3(width, height):
img = io.imread(infile)
dst = transform.resize(img, (439, 371))
io.imsave(outfile, dst)
fixed_size2(371, 439)
src:476x402
resized:439x371
How can you pack 2000 pixels into a box that only holds 1800? You can't.
Putting the same amount of information (stored as pixels in your source image) into a smaller pixelarea only works by
throwing away pixels (i.e. discarding single values or by cropping an image which is not what you want to do)
blending neighbouring pixels into some kind of weighted average and replace say 476 pixels with slightly altered 439 pixels
That is exactly what happens when resizing images. Some kind of algorithm (interpolation=cv2.INTER_CUBIC, others here) tweaks the pixel values to merge/average them so you do not loose too much of information.
You can try to change the algorithm or you can apply further postprocessing ("sharpening") to enrich the contrasts again.
Upon storing the image, certain formats do "lossy" storage to minimize file size (JPG) others are lossless (PNG, TIFF, JPG2000, ...) which further might blur your image if you choose a lossy image format.
See
Shrink/resize an image without interpolation
How can I sharpen an image in OpenCV?
Here is the link I find
How do I find an image contained within an image
And I get the code in the link above.
Here is my code
import re
import os
import time
import cv2
from cv2 import cv
METHOD = cv.CV_TM_SQDIFF_NORMED
ROOTDIR = 'GeneralIMG/'
# Load The Deck Img
LARGE_IMAGE = cv2.imread('deck.bmp')
for subdir, dirs, files in os.walk(ROOTDIR):
for myfile in files:
filepath = os.path.join(subdir, myfile)
# Read the images from the file
# small_image = cv2.imread(myfile)
# small_image = cv2.imread('GeneralIMG/cfrB.bmp')
Ffile = subdir + myfile
small_image = cv2.imread(Ffile)
result = cv2.matchTemplate(small_image, LARGE_IMAGE, METHOD)
# We want the minimum squared difference
mn,_,mnLoc,_ = cv2.minMaxLoc(result)
MPx,MPy = mnLoc
if MPx == 0 and MPy == 0:
print 'Match failure!'
else:
print MPx, MPy
print re.sub(r"B|D", "", os.path.splitext(myfile)[0])
# Draw the rectangle:
# Extract the coordinates of our best match
MPx,MPy = mnLoc
# Step 2: Get the size of the template. This is the same size as the match.
trows,tcols = small_image.shape[:2]
# Step 3: Draw the rectangle on LARGE_IMAGE
cv2.rectangle(LARGE_IMAGE, (MPx,MPy),(MPx+tcols,MPy+trows),(0,0,255),2)
# Display the original image with the rectangle around the match.
cv2.imshow('output',LARGE_IMAGE)
# The image is only displayed if we call this
cv2.waitKey(0)
# time.sleep(5)
This is the small pic which I want to find in the large image but the large image don't contain the small image. To my surprise the matchTemplate still get the result.
12~07_00-03-03.bmp http://7xpvdr.com1.z0.glb.clouddn.com/12~07_00-03-03.bmp
But the match result I get is not accurate enough like the pic below. The red rectangle is the match result.
12~07_00-01-58.bmp http://7xpvdr.com1.z0.glb.clouddn.com/12~07_00-01-58.bmp
Here I want to find exact the same pic in the large one. If not contain it, just return a false will be fine. I don't want a fuzzy search what should I do?
--- update ---
this is the small img:
small img
This is the original larger bmp image
large image
When the image is uploaded the format will be changed. The small img is png file, and the larger is bmp.
Thing is I wonder if the matchtemplate use the fuzzy search here. So the issue here why I get the wrong search result seems reasonable. I want to know how to make the search exactly. Thx~
update:
I check the doc of the [matchtemplate]
And I find this which means it is a best match search not perfect match.
So How can I make it perfect match ?
What is template matching?
Template matching is a technique for finding areas of an image that match (are similar) to a template image (patch).
Have you tried applying a threshold on the results given by minMaxLoc?
I never used matchTemplate and minMaxLoc so I don't really know how it works, but from what I understand, if what you want is a perfect match, then the value you are looking for could possibly be 0 (or 1, depending on your METHOD parameter). So if you discard every other value, you shouldn't get positive results unless you have a perfect match.
You can get perfect matching using cv.matchTemplate:
use method cv.TM_SQDIFF and threshold the absolute values of the result at <= 1/16
Mathematically all patches with perfect matching should have a squared diff of 0, not [-0.0625,0.0625]. However, the optimization in the actual implementation of cv.matchTemplate result in slight differences (at least the function ippiSqrDistanceNorm used at OpenCV 4.5.1 did for uint8 input and 3x3 uint8 masks)
Note that the matching compares starting from the left/top corner, not the center of the template, so if you want to get all pixels with the exact surrounding as your template, you have to add an offset of half the template's width and height.
I have to find count of pixels of RGB which is using by RGB values. So i need logic for that one.
Example.
i have image called image.jpg. That image contains width = 100 and height = 100 and Red value is 128. Green is 0 and blue is 128. so that i need to find how much RGB pixels have that image. can anyone help?
As already mentioned in this question, by using Pillow you can do the following:
from PIL import Image
im = Image.open('image.jpg', 'r')
If successful, this function returns an Image object. You can now use instance attributes to examine the file contents:
width, height = im.size
pixel_values = list(im.getdata())
print(im.format, im.size, im.mode)
The format attribute identifies the source of an image. If the image was not read from a file, it is set to None. The mode attribute defines the number and names of the bands in the image, and also the pixel type and depth. Common modes are “L” (luminance) for greyscale images, “RGB” for true color images, and “CMYK” for pre-press images.
I'm using PIL to scale images that range anywhere from 600px wide to 2400px wide down to around 200px wide. I've already incorporated Image.ANTIALIAS and set quality=95 to try and get the highest quality image possible.
However the scaled down images still have pretty poor quality compared to the originals.
Here's the code that I'm using:
# Open the original image
fp = urllib.urlopen(image_path)
img = cStringIO.StringIO(fp.read())
im = Image.open(img)
im = im.convert('RGB')
# Resize the image
resized_image = ImageOps.fit(im, size, Image.ANTIALIAS)
# Save the image
resized_image_object = cStringIO.StringIO()
resized_image.save(resized_image_object, image_type, quality=95)
What's the best way to scale an image along these ratios while preserving as much of the image quality as possible?
I should note that my primary goal is get the maximum quality image possible. I'm not really concerned with how efficient the process is time wise.
If you can't get results with the native resize options in PIL, you can manually calculate the resize pixel values by running them through your own resizing function. There are three main algorithms (that I know of) for resizing images:
Nearest Neighbor
Bilinear Interpolation
Bicubic Interpolation
The last one will produce the highest quality image at the longest calculation time. To do this, imagine the pixel layout of the the smaller image, then scale it up to match the larger image and think about where the new pixel locations would be over the old ones. Then for each new pixel take the average value of the 16 nearest pixels (4x4 radius around it) and use that as its new value.
The resulting values for each of the pixels in the small image will be a smooth but clear resized version of the large image.
For further reading look here: Wikipedia - Bicubic interpolation
Try a different approach. I'm not sure if this will help, but I did something similar a while back:
https://stackoverflow.com/a/13211834/1339024
It may be that the original image on the urlpath is not that great quality to begin with. But if you want, try my script. I made it to shrink images in a given directory, but this portion could be of use:
parentDir = "Some\\Path"
width = 200
height = 200
cdpi = 75
cquality = 95
a = Image.open(parentDir+'\\'+imgfile) # Change this to your url type
iw,ih = a.size
if iw > width or ih > height:
pcw = width/float(iw)
pch = height/float(ih)
if pcw <= pch:
LPC = pcw
else:
LPC = pch
if 'gif' in imgfile:
a = a.convert("RGB")#,dither=Image.NONE)
a = a.resize((int(iw*LPC),int(ih*LPC)),Image.ANTIALIAS)
a = a.convert("P", dither=Image.NONE, palette=Image.ADAPTIVE)
a.save(outputDir+"\\"+imgfile,dpi=(cdpi,cdpi), quality=cquality)
else:
a = a.resize((int(iw*LPC),int(ih*LPC)),Image.ANTIALIAS)
a.save(outputDir+"\\"+imgfile,dpi=(cdpi,cdpi), quality=cquality)