This commit is contained in:
Louis Heredero 2023-12-04 15:18:37 +01:00
parent 309088e5d2
commit e33f77b46e
18 changed files with 366 additions and 0 deletions

View File

@ -8,5 +8,8 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="scala-sdk-2.13.12" level="project" /> <orderEntry type="library" name="scala-sdk-2.13.12" level="project" />
<orderEntry type="library" name="bridj-0.7.0" level="project" />
<orderEntry type="library" name="slf4j-api-1.7.2" level="project" />
<orderEntry type="library" name="webcam-capture-0.3.12" level="project" />
</component> </component>
</module> </module>

BIN
libs/bridj-0.7.0.jar Normal file

Binary file not shown.

BIN
libs/slf4j-api-1.7.2.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
res/Dead_tree.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
res/collins_eileen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

BIN
res/grace_hopper.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
res/imageProcessing.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
res/mask.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
res/mask640x480.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
res/moire1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

BIN
res/moire2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
res/rice.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,13 @@
package imagefilters
/**
* This class implements the various image filters
*/
object ImageFilters {
def duplicate(a: Array[Array[Int]]): Array[Array[Int]] = {
/* TODO: Write your code hereunder */
return Array.empty
}
}

View File

@ -0,0 +1,14 @@
package imagefilters
import isc.graphics.ImageGraphics
object ImageProcessingApp extends App {
val imageFile = "./res/collins_eileen.png"
val org = new ImageGraphics(imageFile, "Original", -500, -250)
val dest = new ImageGraphics(imageFile, "Duplicate", 0, -250)
// Simple copy and display
val newPixels = ImageFilters.duplicate(org.getPixelsBW())
dest.setPixelsBW(newPixels)
}

View File

@ -0,0 +1,241 @@
package isc.graphics
import java.awt._
import java.awt.image.BufferedImage
import java.io.{File, FileInputStream}
import javax.imageio.ImageIO
import javax.swing.{JFrame, JPanel}
/**
* [ImageGraphics] helpers functions in companion object.
*/
object ImageGraphics {
/**
* Converts a color array to a black-or-white array
*
* @param c The color array
* @return The array converted to BW
*/
def convertToGray(c: Array[Array[Color]]): Array[Array[Color]] = {
val w = c.length
val h = c(0).length
val values = Array.ofDim[Color](w, h)
// FIXME this is slow
for (i <- 0 until w) {
for (j <- 0 until h) {
val col = c(i)(j)
val intColor = (0.3 * col.getRed + 0.59 * col.getGreen + 0.11 * col.getBlue).toInt
values(i)(j) = new Color(intColor, intColor, intColor)
}
}
values
}
def convertToGrayInt(c: Array[Array[Color]]): Array[Array[Int]] = {
val w = c.length
val h = c(0).length
val values = Array.ofDim[Int](w, h)
for (i <- 0 until w) {
for (j <- 0 until h) {
val col = c(i)(j)
val intColor = (0.3 * col.getRed + 0.59 * col.getGreen + 0.11 * col.getBlue).toInt
values(i)(j) = intColor
}
}
values
}
def main(args: Array[String]): Unit = {
val imageUsed = "res/grace_hopper.jpg"
val org = new ImageGraphics(imageUsed, "Original", 0, 0)
}
}
/**
* This class was made to deal with images as multidimensional arrays.
* Mainly used in the <code>ImageProcessing</code> lab. It expects the images to reside in the <code>src</code> directory
*
* @author Pierre-André Mudry
* @version 1.0
* @constructor
*
* @param filePath the path of the file, relative to the project. For instance, "./res/grace_hopper.jpg"
* @param windowTitle the title
* @param xPositionOffset the x offset
* @param yPositionOffset the y offet
*/
class ImageGraphics(val filePath: String, val windowTitle: String,
val xPositionOffset: Int, val yPositionOffset: Int) extends JFrame {
private var imgBuffer: BufferedImage = null
private var w = 0
private var h = 0
class ImgPanel extends JPanel {
override def paint(g: Graphics): Unit = {
super.paint(g)
g.drawImage(imgBuffer, 0, 0, null)
g.dispose()
}
}
val imgPanel = new ImgPanel()
try { // Fill the frame content with the image
try {
imgBuffer = ImageIO.read(new FileInputStream(new File(filePath)))
w = imgBuffer.getWidth
h = imgBuffer.getHeight
} catch {
case e: Exception =>
println("Could not load directly, using classpath.")
}
// If the first technique failed, try using resource instead
if (imgBuffer == null) {
try {
imgBuffer = ImageIO.read(classOf[ImageGraphics].getResource(filePath))
w = imgBuffer.getWidth
h = imgBuffer.getHeight
} catch {
case e: Exception =>
System.err.println("Could not find image " + filePath + ", exiting !")
e.printStackTrace()
System.exit(-1)
}
}
this.setResizable(false)
this.setTitle(windowTitle)
this.setLayout(new BorderLayout())
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
imgPanel.setPreferredSize(new Dimension(imgBuffer.getWidth, imgBuffer.getHeight))
this.add(imgPanel, BorderLayout.CENTER)
this.pack()
// Get the size of the screen
val dim = Toolkit.getDefaultToolkit.getScreenSize
// Determine the new location of the window
val lw = this.getSize.width
val lh = this.getSize.height
val x = (dim.width - lw) / 2 + xPositionOffset
val y = (dim.height - lh) / 2 + yPositionOffset
// Move the window
this.setLocation(x, y)
this.setVisible(true)
} catch {
case e: Exception =>
e.printStackTrace()
}
/**
* Sets a grayscale pixel, does not sets values for invalid pixels
* outside the screen. Does not repaint the screen either because it
* is slow.
*
* @param x
* @param y
* @param intensity
*/
def setPixelBW(x: Int, y: Int, intensity: Int): Unit = {
if (!((x < 0) || (y < 0) || (x >= w) || (y >= h)))
imgBuffer.setRGB(x, y, intensity << 16 | intensity << 8 | intensity)
}
/**
* Sets an array of grayscale pixels (from 0 to 255) and displays them
*
* @param pixels
*/
def setPixelsBW(pixels: Array[Array[Int]]): Unit = {
try {
if (pixels(0).length != h || pixels.length != w) throw new Exception("Invalid size of the pixel array !")
for (i <- 0 until w) {
for (j <- 0 until h) {
val c = pixels(i)(j) << 16 | pixels(i)(j) << 8 | pixels(i)(j)
imgBuffer.setRGB(i, j, c)
}
}
this.repaint()
} catch {
case e: Exception =>
e.printStackTrace()
}
}
/**
* Sets an array of pixels of Color and displays them
*
* @param pixels
*/
def setPixelsColor(pixels: Array[Array[Color]]): Unit = {
try {
if (pixels(0).length != h || pixels.length != w) throw new Exception("Invalid size of the pixel array !")
for (i <- 0 until w) {
for (j <- 0 until h) {
imgBuffer.setRGB(i, j, pixels(i)(j).getRGB)
}
}
this.repaint()
} catch {
case e: Exception =>
e.printStackTrace()
}
}
/**
* Gets a single pixel from the background image and returns its
* grayscale value
*
* @param x the x coordinate
* @param y the y coordinate
* @return the pixel
*/
def getPixelBW(x: Int, y: Int): Int =
if ((x < 0) || (y < 0) || (x >= w) || (y >= h)) {
0
}
else {
// Inside the image. Make the gray conversion and return the value
val c = new Color(imgBuffer.getRGB(x, y))
(0.3 * c.getRed + 0.59 * c.getGreen + 0.11 * c.getBlue).toInt
}
/**
* Gets the array of the pixels (which have been converted to grayscale
* if required)
*
* @return The arrays of gray pixels
*/
def getPixelsBW(): Array[Array[Int]] = {
val values = Array.ofDim[Int](w, h)
for (i <- 0 until w) {
for (j <- 0 until h) {
val c = new Color(imgBuffer.getRGB(i, j))
values(i)(j) = (0.3 * c.getRed + 0.59 * c.getGreen + 0.11 * c.getBlue).toInt
}
}
values
}
/**
* Gets the array of the pixels as Colors (see #Color)
*
* @return The arrays of pixels
*/
def getPixelsColor(): Array[Array[Color]] = {
val values = Array.ofDim[Color](w, h)
for (i <- 0 until w) {
for (j <- 0 until h) {
values(i)(j) = new Color(imgBuffer.getRGB(i, j))
}
}
values
}
}

View File

@ -0,0 +1,95 @@
package livefilter
import com.github.sarxos.webcam.WebcamPanel.DrawMode
import com.github.sarxos.webcam.{Webcam, WebcamImageTransformer, WebcamPanel, WebcamResolution}
import java.awt.image.BufferedImage
import java.awt.{Color, Dimension}
import java.io.{File, FileInputStream}
import javax.imageio.ImageIO
import javax.swing.JFrame
object LiveFilter {
def main(args: Array[String]): Unit = {
new LiveFilter()
}
}
/**
* A live filter class using VGA resolution
*/
class LiveFilter extends WebcamImageTransformer {
val size: Dimension = WebcamResolution.VGA.getSize
val MASK: String = "./res/mask640x480.png"
val videoMask: Array[Array[Int]] = toBW(ImageIO.read(new FileInputStream(new File(MASK))))
// Gets default webcam and sets image transformer to this (transformer will modify
// image after it's been received from webcam, in this case it will rotate it)
val webcam: Webcam = Webcam.getDefault
//val webcam: Webcam = Webcam.getWebcamByName("/dev/video2")
webcam.setViewSize(size)
println(size)
webcam.setImageTransformer(this)
webcam.open
// Create a window
val window = new JFrame("Test filter")
// Creates a panel to put the webcam image in it
val panel = new WebcamPanel(webcam)
panel.setFPSDisplayed(true)
panel.setDrawMode(DrawMode.FIT)
// Add panel to window
window.add(panel)
window.pack()
window.setVisible(true)
window.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
def toBW(img: BufferedImage): Array[Array[Int]] = {
val o = Array.ofDim[Int](img.getWidth(), img.getHeight())
for (x <- o.indices) {
for (y <- o(0).indices) {
val c = new Color(img.getRGB(x, y))
o(x)(y) = (0.3 * c.getRed + 0.59 * c.getGreen + 0.11 * c.getBlue).toInt
}
}
o
}
def toArray(image: BufferedImage): Array[Array[Color]] = {
val out = Array.ofDim[Color](image.getWidth, image.getHeight)
for (x <- out.indices; y <- out(0).indices) {
out(x)(y) = new Color(image.getRGB(x, y))
}
out
}
private def updateImage(in: Array[Array[Color]], out: BufferedImage): Unit = {
for (x <- in.indices; y <- in(0).indices) {
out.setRGB(x, y, in(x)(y).getRGB)
}
}
/**
* Applies the various filters to the buffer
*
* @param image The input image
* @return The filtered image
*/
override def transform(image: BufferedImage): BufferedImage = {
val img: Array[Array[Color]] = toArray(image)
// TODO Complete here by changing the assignment with your filters
val filtered: Array[Array[Color]] = img
updateImage(filtered, image)
return image
}
}