class SharpnessMeter
Focus Inspector - The focus inspection and lens calibration software.
Copyright © 2012 by Chris Schlaeger <chris@linux.com>
This program is Open Source software; you can redistribute it and/or modify it under the terms of MIT license as shipped with this software.
Public Class Methods
new(imageFile)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 13 def initialize(imageFile) @imageFile = imageFile @minSquareSize = 100 end
Public Instance Methods
measure(x, y)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 18 def measure(x, y) image = Magick::Image.read(@imageFile).first x, y, sqSize = findBlackSquare(image, x, y) crop = cropQuadrants(image, x, y) #ImageViewer.new(image) colorHistogram = crop.color_histogram bwHistogram = convertHistToBW(colorHistogram) calcSharpness(bwHistogram, crop) end
Private Instance Methods
calcSharpness(bwHist, image)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 205 def calcSharpness(bwHist, image) peakBlackIndex = findHistogramPeak(bwHist, true) peakWhiteIndex = findHistogramPeak(bwHist, false) hEdge = 0 image.columns.times do |c| hEdge += edgeSharpness(image, c, 0, 0, 1) end hEdge /= image.columns vEdge = 0 image.rows.times do |r| vEdge += edgeSharpness(image, 0, r, 1, 0) end vEdge /= image.rows maxEdge = peakWhiteIndex - peakBlackIndex ((hEdge + vEdge) / 2.0) / maxEdge end
color(image, x, y, radius = 2)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 31 def color(image, x, y, radius = 2) blackCount = 0 whiteCount = 0 greyCount = 0 (-radius).upto(radius) do |xi| (-radius).upto(radius) do |yi| col = image.pixel_color(x + xi, y + yi) val = (col.red + col.green + col.blue) / 3 if val < 0x6000 blackCount += 1 elsif val > 0xA000 whiteCount += 1 else greyCount += 1 end end end if blackCount > whiteCount && blackCount > greyCount :black elsif whiteCount > blackCount && whiteCount > greyCount :white else :grey end end
convertHistToBW(cHist)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 174 def convertHistToBW(cHist) bwHist = Hash.new(0) cHist.each do |rgb, val| # The color histogram contains the values for 16 bit RGB colors. bwHist[(rgb.red + rgb.green + rgb.blue) / 3] += val end #bwHist.each { |i, v | Log.debug("Color #{i}: #{v}") } bwHist end
cropQuadrants(image, bx, by)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 148 def cropQuadrants(image, bx, by) probeSize = @minSquareSize # Return a probeSize sized rectangle with the top left corner of the # black square in the center spot. radius = @minSquareSize / 2 x = bx - radius y = by - radius #showMarkedImage(image, x, y, probeSize, probeSize) unless color(image, x, y, radius) == :black Log.error("Top-left quadrant is not black") end unless color(image, x, y + @minSquareSize, radius) == :white Log.error("Bottom-left quadrant is not white") end unless color(image, x + @minSquareSize, y + @minSquareSize, radius) == :black Log.error("Bottom-right quadrant is not black") end unless color(image, x + @minSquareSize, y, radius) == :white Log.error("Top-right quadrant is not white") end image.crop(x, y, probeSize, probeSize) end
edgeSharpness(image, x, y, dx, dy)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 226 def edgeSharpness(image, x, y, dx, dy) biggestDelta = 0 while (x >= 0 && x < image.columns && y >= 0 && y < image.rows) nx = x + dx ny = y + dy col = image.pixel_color(x, y) val1 = (col.red + col.green + col.blue) / 3 col = image.pixel_color(nx, ny) val2 = (col.red + col.green + col.blue) / 3 delta = (val1 - val2).abs biggestDelta = delta if biggestDelta < delta x = nx y = ny end biggestDelta end
findBlackSquare(image, x, y)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 92 def findBlackSquare(image, x, y) # Find a pixel inside of a black square by moving along a spiral line. stepInc = 11 steps = stepInc stepCount = 0 dir = :right while color(image, x, y) != :black case dir when :right x += steps dir = :down unless stepCount % 2 == 0 when :down y += steps dir = :left unless stepCount % 2 == 0 when :left x -= steps dir = :up unless stepCount % 2 == 0 when :up y -= steps dir = :right unless stepCount % 2 == 0 end if stepCount < 3 stepCount += 1 else stepCount = 0 steps += stepInc end Log.debug("x: #{x} y: #{y}") if x < 0 || x >= image.columns || y < 0 || y >= image.rows Log.error("No black square found.") end end #image.crop!(x - 15, y - 15, 30, 30) #ImageViewer.new(image) #exit blackSqX0 = findEdge(image, x, y, -1, 0)[0] blackSqX1 = findEdge(image, x, y, 1, 0)[0] blackSqY0 = findEdge(image, x, y, 0, -1)[1] blackSqY1 = findEdge(image, x, y, 0, 1)[1] # Compute the edge length of the square. sqWidth = blackSqX1 - blackSqX0 + 1 sqHeight = blackSqY1 - blackSqY0 + 1 Log.debug("Square size is #{sqWidth} x #{sqHeight}") if sqWidth < @minSquareSize || sqHeight < @minSquareSize Log.error("The size (#{sqWidth} x #{sqHeight}) of the detected " + "black square is too small.") end #showMarkedImage(image, blackSqX0, blackSqY0, sqWidth, sqHeight) [ blackSqX0, blackSqY0, (sqWidth + sqHeight) / 2 ] end
findEdge(image, x, y, dx, dy)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 69 def findEdge(image, x, y, dx, dy) startCol = color(image, x, y) raise 'Starting point must not be grey.' if startCol == :grey while (c = color(image, x, y)) == :grey || c == startCol if c == startCol sx = x sy = y end x += dx y += dy if x < 0 || x >= image.columns || y < 0 || y >= image.rows Log.error("Cannot detect the edge of the square (#{dx}, #{dy}).") end end ex = x ey = y # The edge is located right in the middle of the grey zone. [ sx + (ex - sx) / 2, sy + (ey - sy) / 2 ] end
findHistogramPeak(hist, black)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 186 def findHistogramPeak(hist, black) peakIndex = nil if black sIdx = 0 eIdx = 0x7FFF else sIdx = 0x8000 eIdx = 0xFFFF end sIdx.upto(eIdx) do |i| if peakIndex.nil? || hist[peakIndex] < hist[i] peakIndex = i end end peakIndex end
showMarkedImage(image, x, y, w, h)
click to toggle source
# File lib/focusinspector/SharpnessMeter.rb, line 57 def showMarkedImage(image, x, y, w, h) painter = Magick::Draw.new painter.opacity(0) painter.stroke('red') painter.stroke_width = 9 painter.rectangle(x, y, x + w, y + h) painter.draw(image) ImageViewer.new(image) exit end