How hard could this be? Q(n)…

An interesting talk tomorrow in NJ, by Douglas Hofstadter…


In 1963, while playing a novel number-theoretical game with a friend, I dreamt up a curious recursive definition for an integer-valued function, which I dubbed “Q(n)”. Here is the recursion:

Q(n) = Q(n-Q(n-1)) + Q(n-Q(n-2))

The two initial values I supplied were Q(1) = 1 and Q(2) = 1. This function’s behavior turned out to be very unpredictable. I spent a good deal of time exploring it computationally, and also invented and explored some variations on the theme. To my frustration, though, I wasn’t able to prove anything about Q(n) (not even that it existed for all positive values of n!), no matter how hard I worked. Eventually, as often tends to happen when one has pushed oneself as far as one can go and has hit up against one’s limits, Q(n) slowly faded into the background of my life. Many years later, my mathematician/physicist
friend Greg Huber proposed that we go back to the canonical and very natural but unsolved questions about the mysterious function Q(n), with its magnetic appeal and crystalline beauty, and carefully study them. I went for Greg’s bait hook, line, and sinker, but soon I found, to my great frustration, that unlike Greg, who had made some small progress analytically, I was completely unable to prove anything analytically about Q(n). Soon Greg found himself in a similar position of frustration. After a period of stagnation, finding ourselves in a box canyon with no escape route except using a computer to do experimental mathematics, together he and I invented a two-parameter family of functions closely related to Q(n) and we explored their behavior computationally. We found some delightful surprises and some deep insights. However, despite all the progress, a lot of mystery remained (and still remains). In this talk, I will mainly describe Greg Huber’s and my collaborative discoveries.


Face detection with a webcam, using only OpenCV with Java, and not “javacv”

This is adapted from

In class window (yes, lowercase… not standard, but it’s how they did it…)

package edu.udallas.cs;

import javax.swing.JFrame;

import org.opencv.core.Mat;
import org.opencv.highgui.VideoCapture;

public class window {  
    public static void main(String arg[]){  
        // Load the native library.  
        String window_name = "Capture - Face detection";  
        JFrame frame = new JFrame(window_name);  
        processor my_processor=new processor();  
        My_Panel my_panel = new My_Panel();  
        //-- 2. Read the video stream  
        Mat webcam_image=new Mat();  
        VideoCapture capture =new VideoCapture(-1);   
        if( capture.isOpened())  
            while( true )  
                if( !webcam_image.empty() )  
                    //-- 3. Apply the classifier to the captured image  
                    //-- 4. Display the image  
                    my_panel.MatToBufferedImage(webcam_image); // We could look at the error...  
                    System.out.println(" --(!) No captured frame -- Break!");   

In class My_Panel:

package edu.udallas.cs;

 * Captures the camera stream with OpenCV  
 * Search for the faces  
 * Display a circle around the faces using Java
import java.awt.*;  
import java.awt.image.BufferedImage;  
import java.awt.image.DataBufferByte;  
import javax.swing.*;  
import org.opencv.core.Core;  
import org.opencv.core.Mat;  
import org.opencv.core.MatOfRect;  
import org.opencv.core.Point;  
import org.opencv.core.Rect;  
import org.opencv.core.Scalar;  
import org.opencv.core.Size;  
import org.opencv.highgui.VideoCapture;  
import org.opencv.imgproc.Imgproc;  
import org.opencv.objdetect.CascadeClassifier;  
class My_Panel extends JPanel{  
    private static final long serialVersionUID = 1L;  
    private BufferedImage image;  
    // Create a constructor method  

    public My_Panel(){  
     * Converts/writes a Mat into a BufferedImage.  
     * @param matrix Mat of type CV_8UC3 or CV_8UC1  
     * @return BufferedImage of type TYPE_3BYTE_BGR or TYPE_BYTE_GRAY  
    public boolean MatToBufferedImage(Mat matBGR){  
        long startTime = System.nanoTime();  
        int width = matBGR.width(), height = matBGR.height(), channels = matBGR.channels() ;  
        byte[] sourcePixels = new byte[width * height * channels];  
        matBGR.get(0, 0, sourcePixels);  
        // create new image and get reference to backing data  
        image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);  
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();  
        System.arraycopy(sourcePixels, 0, targetPixels, 0, sourcePixels.length);  
        long endTime = System.nanoTime();  
        System.out.println(String.format("Elapsed time: %.2f ms", (float)(endTime - startTime)/1000000));  
        return true;  
    public void paintComponent(Graphics g){  
        if (this.image==null) return;  
        g.drawImage(this.image,10,10,2*this.image.getWidth(),2*this.image.getHeight(), null);  
        //g.drawString("This is my custom Panel!",10,20);  

class processor {  
    private CascadeClassifier face_cascade;  
    // Create a constructor method  
    public processor(){  
        face_cascade=new CascadeClassifier("/home/hochberg/Research/OpenCV/opencv-2.4.8/data/haarcascades/haarcascade_profileface.xml");  
            System.out.println("--(!)Error loading A\n");  
            System.out.println("Face classifier loooaaaaaded up");  
    public Mat detect(Mat inputframe){    
        long startTime = System.nanoTime();  
        Mat mRgba=new Mat();  
        Mat mGrey=new Mat();  
        MatOfRect faces = new MatOfRect();  
        Imgproc.cvtColor( mRgba, mGrey, Imgproc.COLOR_BGR2GRAY);  
        Imgproc.equalizeHist( mGrey, mGrey );  
        face_cascade.detectMultiScale(mGrey, faces);  
        long endTime = System.nanoTime();  
        System.out.println(String.format("Detect time: %.2f ms", (float)(endTime - startTime)/1000000));  
        System.out.println(String.format("Detected %s faces", faces.toArray().length));  
        for(Rect rect:faces.toArray())  
            Point center= new Point(rect.x + rect.width*0.5, rect.y + rect.height*0.5 );  
            Core.ellipse( mRgba, center, new Size( rect.width*0.5, rect.height*0.5), 0, 0, 360, new Scalar( 255, 0, 255 ), 4, 8, 0 );  
        return mRgba;